Linq To SQL Group By and Sum - linq-to-sql

Her is an image showing a the table i have, b the grid i need to display.
opps cant post image. ill try to explain. My table have four colums.
Project Number(String)
ItemNumber(String)
Location(String)
Qty.(Real).
My grid need to look like this.
ProjectNumber
ItemNumber
QtyMain.
QtyOther.
I Need to write a linq query Grouping evry line so i will se 1 Line pr Project/ItemNumber combination summing qty into 2 differetn colums 1 showing to qty where location is main and 1 showing the qty where location is not (!=) main. Can linq do this for me, or how can thsi be done?

public class Foo
{
public Int32 ProjectNumber;
public String ItemNumber;
public String InventLocation;
public Int32 Qty;
}
void Main()
{
List<Foo> foos = new List<Foo>(new[]{
new Foo { ProjectNumber = 1, ItemNumber = "a", InventLocation = "Main", Qty = 3 },
new Foo { ProjectNumber = 1, ItemNumber = "a", InventLocation = "Main", Qty = 3 },
new Foo { ProjectNumber = 1, ItemNumber = "a", InventLocation = "Sub", Qty = 2 },
new Foo { ProjectNumber = 1, ItemNumber = "a", InventLocation = "Sub", Qty = 1 },
new Foo { ProjectNumber = 1, ItemNumber = "a", InventLocation = "Sub2", Qty = 5 }
});
var foo = from f in foos
group f by new { f.ProjectNumber, f.ItemNumber } into fGroup
select new {
ProjectNumber = fGroup.Key.ProjectNumber,
ItemNumber = fGroup.Key.ItemNumber,
QtyMain = fGroup.Where (g => g.InventLocation == "Main").Sum (g => g.Qty),
Rest = fGroup.Where (g => g.InventLocation != "Main").Sum (g => g.Qty)
};
foo.Dump();
}
Resulting in:
IEnumerable<> (1 item)
ProjectNumber ItemNumber QtyMain Rest
1 a 6 8

Related

Dynamic History Reference for Variable Assignment

I'm making an indicator that plots the last 5 candles of each user-selected timeframe. Everything else is working (i think lol) besides my scaling/normalize function (it's messing up the wicks/high and low values) and my _lastDiffValue function.
I'm trying to create a function (_lastDiffValue) that runs a while loop and returns a specific integer for a history reference. The integer would be how many times the while loop ran. This way I can find the history reference for a specific condition. The reason I'm trying to do this is because the series I am working with has a lot of repetitive values and I want to find the last different value and assign it to a variable. This is one piece of a very involved indicator (at least for my experience lol).
Here's the code:
// © pipjitsu
//#version=5
indicator("Multi-TF Candles", overlay = false, explicit_plot_zorder = true)
group1 = "Timeframes"
bull_col = input.color(color.blue, "Bullish")
bear_col = input.color(color.new(color.red, 0), "Bearish")
wick_color = input.color(#000000, "Wick Color")
lookback = input.int(6, "Candles per Timeframe")
space = 3
tf1 = input.timeframe("1D", title = "", inline = "Column 1", group = group1)
tf2 = input.timeframe("240", title = "", inline = "Column 1", group = group1)
tf3 = input.timeframe("60", title = "", inline = "Column 1", group = group1)
tf4 = input.timeframe("15", title = "", inline = "Column 1", group = group1)
tf5 = input.timeframe("5", title = "", inline = "Column 1", group = group1)
tf6 = input.timeframe("1", title = "", inline = "Column 1", group = group1)
_makeCandle(_open, _high, _low, _close, _group) =>
if barstate.islast
for i = 1 to lookback
_bias = _close[i] > _open[i] ? bull_col : bear_col
_shift = (i * space) + ((_group - 1) * (space * lookback + 4))
line1 = line.new(bar_index - _shift, _high[i], bar_index - _shift, _low[i], color = wick_color)
line.delete(line1[1])
box1 = box.new((bar_index - 1) - _shift, _open[i], (bar_index + 1) - _shift, _close[i], bgcolor = _bias, border_color = color.black)
box.delete(box1[1])
_lastDiffVal(_val) =>
var float _newVal = _val + 1
var int counter = na
while _val == _newVal
counter := counter + 1
_newVal := _val[counter]
counter
_normalize(_src) =>
_min = 0
_max = 100
var _historicMin = 10e10
var _historicMax = -10e10
_historicMin := math.min(nz(_src, _historicMin), _historicMin)
_historicMax := math.max(nz(_src, _historicMax), _historicMax)
_min + (_max - _min) * (_src - _historicMin) / math.max(_historicMax - _historicMin, 10e-10)
_getData(_tf) =>
[_open, _high, _low, _close] = request.security("", _tf, [open[_lastDiffVal(open)], high[_lastDiffVal(high)], low[_lastDiffVal(low)], close[_lastDiffVal(close)]])
_open := _normalize(_open)
_high := _normalize(_high)
_low := _normalize(_low)
_close := _normalize(_close)
[_open, _high, _low, _close]
_masterFun(_tf, _group) =>
[_open, _high, _low, _close] = _getData(_tf)
_makeCandle(_open, _high, _low, _close, _group)
_masterFun(tf1, 1)
_masterFun(tf2, 2)
_masterFun(tf3, 3)
_masterFun(tf4, 4)
_masterFun(tf5, 5)
_masterFun(tf6, 6)

Android Room how to query related table?

First thing, my data is POKEMON!!! enjoy 😉
I need to do this on the database side, filtering and sorting the returned data isn't an option as using Paging...
I'm using Room I have my database working well but I now want to query the pokemonType list in my relation
Given this data class
data class PokemonWithTypesAndSpecies #JvmOverloads constructor(
#Ignore
var matches : Int = 0,
#Embedded
val pokemon: Pokemon,
#Relation(
parentColumn = Pokemon.POKEMON_ID,
entity = PokemonType::class,
entityColumn = PokemonType.TYPE_ID,
associateBy = Junction(
value = PokemonTypesJoin::class,
parentColumn = Pokemon.POKEMON_ID,
entityColumn = PokemonType.TYPE_ID
)
)
val types: List<PokemonType>,
#Relation(
parentColumn = Pokemon.POKEMON_ID,
entity = PokemonSpecies::class,
entityColumn = PokemonSpecies.SPECIES_ID,
associateBy = Junction(
value = PokemonSpeciesJoin::class,
parentColumn = Pokemon.POKEMON_ID,
entityColumn = PokemonSpecies.SPECIES_ID
)
)
val species: PokemonSpecies?
)
I can get my data with a simple query and even search it
#Query("SELECT * FROM Pokemon WHERE pokemon_name LIKE :search")
fun searchPokemonWithTypesAndSpecies(search: String): LiveData<List<PokemonWithTypesAndSpecies>>
But now what I want is to add filtering on pokemon types which as you can see is a list (which is probably a transaction under the hood) and is in a seperate table, so given a list of string called filters I want to:
only return pokemon that contain an item in filters
sort pokemon by both number of matching types and by ID
So I want my tests to look something like this
val bulbasaurSpeciesID = 1
val squirtleSpeciesID = 2
val charmanderSpeciesID = 3
val charizardSpeciesID = 4
val pidgeySpeciesID = 5
val moltresSpeciesID = 6
val bulbasaurID = 1
val squirtleID = 2
val charmanderID = 3
val charizardID = 4
val pidgeyID = 5
val moltresID = 6
val grassTypeID = 1
val poisonTypeID = 2
val fireTypeID = 3
val waterTypeID = 4
val flyingTypeID = 5
val emptySearch = "%%"
val allPokemonTypes = listOf(
"normal",
"water",
"fire",
"grass",
"electric",
"ice",
"fighting",
"poison",
"ground",
"flying",
"psychic",
"bug",
"rock",
"ghost",
"dark",
"dragon",
"steel",
"fairy",
"unknown",
)
#Before
fun createDb() {
val context = ApplicationProvider.getApplicationContext<Context>()
db = Room.inMemoryDatabaseBuilder(
context, PokemonRoomDatabase::class.java,
).setTransactionExecutor(Executors.newSingleThreadExecutor())
.allowMainThreadQueries()
.build()
pokemonDao = db.pokemonDao()
speciesDao = db.pokemonSpeciesDao()
speciesJoinDao = db.pokemonSpeciesJoinDao()
pokemonTypeDao = db.pokemonTypeDao()
pokemonTypeJoinDao = db.pokemonTypeJoinDao()
}
#After
#Throws(IOException::class)
fun closeDb() {
db.close()
}
#Test
#Throws(Exception::class)
fun testFiltering() {
insertPokemonForFilterTest()
val pokemon =
pokemonDao.searchAndFilterPokemon(search = emptySearch, filters = allPokemonTypes)
.getValueBlocking(scope)
assertThat(pokemon?.size, equalTo(6)) // This fails list size is 9 with the current query
val pokemonFiltered =
pokemonDao.searchAndFilterPokemon(search = emptySearch, filters = listOf("fire", "flying"))
.getValueBlocking(scope)
assertThat(pokemon?.size, equalTo(4))
assertThat(pokemonFiltered!![0].pokemon.name, equalTo("charizard")) // matches 2 filters and ID is 4
assertThat(pokemonFiltered!![1].pokemon.name, equalTo("moltres")) // matches 2 filters and ID is 6
assertThat(pokemonFiltered!![2].pokemon.name, equalTo("charmander")) // matches one filter and ID is 3
assertThat(pokemonFiltered!![3].pokemon.name, equalTo("pidgey")) // mayches one filter and ID is 5
}
private fun insertPokemonForFilterTest() = runBlocking {
insertBulbasaur()
insertSquirtle()
insertCharmander()
insertCharizard()
insertMoltres()
insertPidgey()
}
private fun insertBulbasaur() = runBlocking {
val bulbasaur = bulbasaur()
val grassJoin = PokemonTypesJoin(pokemon_id = bulbasaurID, type_id = grassTypeID)
val poisonJoin = PokemonTypesJoin(pokemon_id = bulbasaurID, type_id = poisonTypeID)
val bulbasaurSpeciesJoin =
PokemonSpeciesJoin(pokemon_id = bulbasaurID, species_id = bulbasaurSpeciesID)
pokemonDao.insertPokemon(bulbasaur.pokemon)
speciesDao.insertSpecies(bulbasaur.species!!)
speciesJoinDao.insertPokemonSpeciesJoin(bulbasaurSpeciesJoin)
pokemonTypeDao.insertPokemonType(pokemonType = bulbasaur.types[0])
pokemonTypeDao.insertPokemonType(pokemonType = bulbasaur.types[1])
pokemonTypeJoinDao.insertPokemonTypeJoin(grassJoin)
pokemonTypeJoinDao.insertPokemonTypeJoin(poisonJoin)
}
private fun insertSquirtle() = runBlocking {
val squirtle = squirtle()
val squirtleSpeciesJoin =
PokemonSpeciesJoin(pokemon_id = squirtleID, species_id = squirtleSpeciesID)
val waterJoin = PokemonTypesJoin(pokemon_id = squirtleID, type_id = waterTypeID)
pokemonDao.insertPokemon(squirtle.pokemon)
speciesDao.insertSpecies(squirtle.species!!)
speciesJoinDao.insertPokemonSpeciesJoin(squirtleSpeciesJoin)
pokemonTypeDao.insertPokemonType(pokemonType = squirtle.types[0])
pokemonTypeJoinDao.insertPokemonTypeJoin(waterJoin)
}
private fun insertCharmander() = runBlocking {
val charmander = charmander()
val fireJoin = PokemonTypesJoin(pokemon_id = charmanderID, type_id = fireTypeID)
val charmanderSpeciesJoin =
PokemonSpeciesJoin(pokemon_id = charmanderID, species_id = charmanderSpeciesID)
pokemonDao.insertPokemon(charmander.pokemon)
speciesDao.insertSpecies(charmander.species!!)
speciesJoinDao.insertPokemonSpeciesJoin(charmanderSpeciesJoin)
pokemonTypeDao.insertPokemonType(pokemonType = charmander.types[0])
pokemonTypeJoinDao.insertPokemonTypeJoin(fireJoin)
}
private fun insertCharizard() = runBlocking {
val charizard = charizard()
val charizardSpeciesJoin =
PokemonSpeciesJoin(pokemon_id = charizardID, species_id = charizardSpeciesID)
val fireJoin = PokemonTypesJoin(pokemon_id = charizardID, type_id = fireTypeID)
val flyingJoin = PokemonTypesJoin(pokemon_id = charizardID, type_id = flyingTypeID)
pokemonDao.insertPokemon(charizard.pokemon)
speciesDao.insertSpecies(charizard.species!!)
speciesJoinDao.insertPokemonSpeciesJoin(charizardSpeciesJoin)
pokemonTypeDao.insertPokemonType(pokemonType = charizard.types[0])
pokemonTypeDao.insertPokemonType(pokemonType = charizard.types[1])
pokemonTypeJoinDao.insertPokemonTypeJoin(fireJoin)
pokemonTypeJoinDao.insertPokemonTypeJoin(flyingJoin)
}
private fun insertPidgey() = runBlocking {
val pidgey = pidgey()
val pidgeySpeciesJoin =
PokemonSpeciesJoin(pokemon_id = pidgeyID, species_id = pidgeySpeciesID)
val flyingJoin = PokemonTypesJoin(pokemon_id = pidgeyID, type_id = flyingTypeID)
pokemonDao.insertPokemon(pidgey.pokemon)
speciesDao.insertSpecies(pidgey.species!!)
speciesJoinDao.insertPokemonSpeciesJoin(pidgeySpeciesJoin)
pokemonTypeDao.insertPokemonType(pokemonType = pidgey.types[0])
pokemonTypeJoinDao.insertPokemonTypeJoin(flyingJoin)
}
private fun insertMoltres() = runBlocking {
val moltres = moltres()
val moltresSpeciesJoin =
PokemonSpeciesJoin(pokemon_id = moltresID, species_id = moltresSpeciesID)
val fireJoin = PokemonTypesJoin(pokemon_id = moltresID, type_id = fireTypeID)
val flyingJoin = PokemonTypesJoin(pokemon_id = moltresID, type_id = flyingTypeID)
pokemonDao.insertPokemon(moltres.pokemon)
speciesDao.insertSpecies(moltres.species!!)
speciesJoinDao.insertPokemonSpeciesJoin(moltresSpeciesJoin)
pokemonTypeDao.insertPokemonType(pokemonType = moltres.types[0])
pokemonTypeDao.insertPokemonType(pokemonType = moltres.types[1])
pokemonTypeJoinDao.insertPokemonTypeJoin(fireJoin)
pokemonTypeJoinDao.insertPokemonTypeJoin(flyingJoin)
}
fun bulbasaur(): PokemonWithTypesAndSpecies = PokemonWithTypesAndSpecies(
pokemon = Pokemon(id = bulbasaurID, name = "bulbasaur"),
species = PokemonSpecies(
id = bulbasaurSpeciesID,
species = "Seed pokemon",
pokedexEntry = "There is a plant seed on its back right from the day this Pokémon is born. The seed slowly grows larger."
),
types = listOf(
PokemonType(id = poisonTypeID, name = "poison", slot = 1),
PokemonType(id = grassTypeID, name = "grass", slot = 2)
)
)
fun squirtle(): PokemonWithTypesAndSpecies = PokemonWithTypesAndSpecies(
pokemon = Pokemon(id = squirtleID, name = "squirtle"),
species = PokemonSpecies(
id = squirtleSpeciesID,
species = "Turtle pokemon",
pokedexEntry = "Small shell pokemon"
),
types = listOf(PokemonType(id = waterTypeID, name = "water", slot = 1))
)
fun charmander(): PokemonWithTypesAndSpecies = PokemonWithTypesAndSpecies(
pokemon = Pokemon(id = charmanderID, name = "charmander"),
species = PokemonSpecies(
id = charmanderSpeciesID,
species = "Fire lizard pokemon",
pokedexEntry = "If the flame on this pokemon's tail goes out it will die"
),
types = listOf(PokemonType(id = fireTypeID, name = "fire", slot = 1))
)
fun charizard(): PokemonWithTypesAndSpecies = PokemonWithTypesAndSpecies(
pokemon = Pokemon(id = charizardID, name = "charizard"),
species = PokemonSpecies(
id = charizardSpeciesID,
species = "Fire flying lizard pokemon",
pokedexEntry = "Spits fire that is hot enough to melt boulders. Known to cause forest fires unintentionally"
),
types = listOf(
PokemonType(id = fireTypeID, name = "fire", slot = 1),
PokemonType(id = flyingTypeID, name = "flying", slot = 2)
)
)
fun moltres(): PokemonWithTypesAndSpecies = PokemonWithTypesAndSpecies(
pokemon = Pokemon(id = moltresID, name = "moltres"),
species = PokemonSpecies(
id = moltresSpeciesID,
species = "Fire bird pokemon",
pokedexEntry = "Known as the legendary bird of fire. Every flap of its wings creates a dazzling flash of flames"
),
types = listOf(
PokemonType(id = fireTypeID, name = "fire", slot = 1),
PokemonType(id = flyingTypeID, name = "flying", slot = 2)
)
)
fun pidgey(): PokemonWithTypesAndSpecies = PokemonWithTypesAndSpecies(
pokemon = Pokemon(id = pidgeyID, name = "pidgey"),
species = PokemonSpecies(
id = pidgeySpeciesID,
species = "Bird pokemon",
pokedexEntry = "Pidgey is a Flying Pokémon. Among all the Flying Pokémon, it is the gentlest and easiest to capture. A perfect target for the beginning Pokémon Trainer to test his Pokémon's skills."
),
types = listOf(PokemonType(id = flyingTypeID, name = "flying", slot = 1))
)
And the query would be
#Query("SELECT * FROM Pokemon INNER JOIN PokemonType, PokemonTypesJoin ON Pokemon.pokemon_id = PokemonTypesJoin.pokemon_id AND PokemonType.type_id = PokemonTypesJoin.type_id WHERE pokemon_name LIKE :search AND type_name IN (:filters) ORDER BY pokemon_id ASC")
fun searchAndFilterPokemon(search: String, filters: List<String>): LiveData<List<PokemonWithTypesAndSpecies>>
I'm guessing this doesn't work because at this point Room hasn't collected the types from the other table and it's probably not even querying a list, I think this part
type_name IN (:filters)
is checking a column against a list when what I want is a List against a list 🤷‍♂️ but honestly I'm happy to just say I've fallen and can't get up 🤣 can anyone help? any help appreciated
Maybe I could misuse some columns' names, but try this query:
#Query("SELECT pok.id, pok.name FROM Pokemon AS pok
INNER JOIN PokemonTypesJoin AS p_join ON pok.id = p_join.pokemon_id
INNER JOIN PokemonType AS pok_type ON pok_type.id = p_join.type_id
WHERE pok.name LIKE :search AND pok_type.name IN (:filters)
GROUP BY pok.id, pok.name ORDER BY count(*) DESC, pok.id ASC")
Have you compared Room to Cmobilecom-JPA for android? JPA is very good at query relationships. The advantage of using JPA (standard) is obvious, making your code reusable on android, server side java, or swing project.
Thanks to #serglytikhonov my query works and now looks like this
#Query("""SELECT * FROM Pokemon
INNER JOIN PokemonTypesJoin
ON Pokemon.pokemon_id = PokemonTypesJoin.pokemon_id
INNER JOIN PokemonType
ON PokemonType.type_id = PokemonTypesJoin.type_id
WHERE pokemon_name LIKE :search AND type_name IN (:filters)
GROUP BY Pokemon.pokemon_id, Pokemon.pokemon_name
ORDER BY count(*) DESC, pokemon_id ASC""")
fun searchAndFilterPokemon(search: String, filters: List<String>): LiveData<List<PokemonWithTypesAndSpecies>>
the main piece being this count(*) and group by many thanks

Passing a table as argument to function in Lua

I want to loop through different indexed tables by only passing the initial table as an argument.
I currently have this table:
local table = {
stuff_1 = {
categories = {},
[1] = {
name = 'wui',
time = 300
}
},
stuff_2 = {
categories = {'stuff_10', 'stuff_11', 'stuff_12'},
stuff_10 = {
categories = {},
[1] = {
name = 'peo',
time = 150
},
[2] = {
name = 'uik',
time = 15
},
[3] = {
name = 'kpk',
time = 1230
},
[4] = {
name = 'aer',
time = 5000
}
},
stuff_11 = {
categories = {},
[1] = {
name = 'juio',
time = 600
}
},
stuff_12 = {
categories = {},
[1] = {
name = 'erq',
time = 980
},
[2] = {
name = 'faf',
time = 8170
}
}
}
I wanted to make a recursive function to check if the name in any of those tables was equal to some certain thing and return a string.
The recursivity lies in the idea of updating this table with whatever ammount I'd like (or until a certain limit).
I don't understand exactly what's wrong since when I try:
for k, v in pairs(table) do
print(k, v, #v.categories)
end
It correctly prints:
stuff_2 table: 0x10abb0 3
stuff_1 table: 0x10aab8 0
But when passing the table as a parameter to the the function below, it gives this error:
[string "stdin"]:84: attempt to get length of field 'categories' (a nil value)
Function:
function checkMessage(table)
local i = 1
local message = ""
for k, v in pairs(table) do
if(#v.categories == 0) then
while(v[i]) do
if(v[i].name == 'opd') then
if(v[i].time ~= 0) then
message = "return_1"
else
message = "return_2"
end
end
i = i + 1
end
else
checkMessage(table[k])
end
end
return message
end
EDIT: The problem lies in not ignoring that when using pairs onto the table, this doesn't just have tables with a category subtable but it also has a table named category, if this is ignored then the problem is fixed.
You're recursing into subtables that don't have a categories field. Trying to access categories on them yields nil, which you then try to use the length operator on. Hence your error:
attempt to get length of field 'categories' (a nil value)
If you can't hand trace your app, put in more print statements or get a line level debugger.

Sort object by another object value inside

Here some complication sorting in my application.
Now i have data object is like following(called pCList):
Object[0]:
Id: 1
comp: Test
med: xyz
condition: valueObject.Condition
Object[1]:
Id: 2
comp: Test1
med: pqr
condition: valueObject.Condition
Object[2]:
Id: 3
comp: Test
med: abc
condition: valueObject.Condition
condition VO Have data like:
condition data1:
conId: 001
cond: abcds
condition data2:
conId: 001
cond: trdfd
condition data3:
conId: 001
cond: dsdsds
For normal sorting i will do as following way;
var sort:ISort = new Sort();
var sortField:ISortField = new SortField("med");
sort.fields = [sortField];
if(pCList != null)
{
pCList.sort = sort;
pCList.refresh();
}
In which pcList is sort by med.
But now, I want to sort by condition.cond
like first come which have cond value abcds then dsdsds then trdfd and so on...
I Have tried it using:
var sort:ISort = new Sort();
var sortField:ISortField = new SortField("condition.cond");
sort.fields = [sortField];
But not succeed. Any help is greatly appreciated.
ISort has a property compareFunction, that can be used for custom sorting. See example below.
var sort:ISort = new Sort();
sort.compareFunction = function(a:Object, b:Object, fields:Array = null):int {
var conditionA:String = a.Condition.cond;
var conditionB:String = b.Condition.cond;
if (conditionA < conditionB) {
return -1;
} else if (conditionA > conditionB) {
return 1;
} else {
return 0;
}
};

Merge three dictionary with Linq-Union

i need to merge three dictionary collection, if key is same i want to add value.
Result is like
One - 5+5 =10
two - 10+20=30
three - 7
four - 2
five - 8
six - 2
Dictionary<string, int> d1 = new Dictionary<string, int>();
d1.Add("one", 5);
d1.Add("two", 10);
d1.Add("three", 7);
Dictionary<string, int> d2 = new Dictionary<string, int>();
d2.Add("four", 2);
d2.Add("two", 20);
d2.Add("five", 8);
Dictionary<string, int> d3 = new Dictionary<string, int>();
d3.Add("one", 5);
d3.Add("six", 2);
Union: ignore the matching resultset.
var uQuery = (from a in d1 select a).Union(from b in d2 select b).GroupBy(grp=>grp.Key );
You should use Concat instead of Union. Union will treat the key value pair ["one", 5] as duplicated in d1 and d3, and therefore exclude one instance of it, giving this result:
"one", 5
"two", 30
"three", 7
"four", 2
"five", 8
"six", 2
var result = d1.Concat(d2.Concat(d3)).GroupBy(keyValuePair => keyValuePair.Key).ToDictionary(group => group.Key, grp => grp.Sum(kvp => kvp.Value));
or perhaps more readably:
var union = d1.Concat(d2.Concat(d3));
var groupBy = union.GroupBy(keyValuePair => keyValuePair.Key);
var result = groupBy.ToDictionary(group => group.Key, grp => grp.Sum(kvp => kvp.Value));