I want to calculate the average fuel consumption for every car in my table.
I have a spendforfuel table with IdCar, Odometer, Quantity fields.
Odometer field is current mileage.
Quantity are the litres consumed between the current mileage and last detected mileage.
Here is my formula:
100 / ( (MAX(Odometer) - MIN(Odometer)) / (SUM(Quantity) - FIRST(Quantity) ) )
Here is what I did:
$q = $this->db->select()
->from(array('s1' => 'spendforfuel'), array('fuel_consumption' => '100 / ( s2.odometer_sum / ( s3.quantity_sum - s4.first_quantity ) )'))
->joinLeft(array('s2' => 'spendforfuel'), 's2.IdCar = s1.IdCar', array('odometer_sum' => 'MAX(s2.Odometer) - MIN(s2.Odometer)'))
->joinLeft(array('s3' => 'spendforfuel'), 's3.IdCar = s1.IdCar', array('quantity_sum' => 'SUM(s3.Quantity)'))
->joinLeft(array('s4' => 'spendforfuel'), 's4.IdCar = s1.IdCar', array('first_quantity' => 's4.Quantity'))
->where('s4.Odometer > ?', 0)
->limit('1 ASC')
->group('s1.CarId')
->where('s1.CarId = ?', 76);
I am not sure if I have to use joins at all. Any ideas?
Related
I have the following sql query
SELECT statusId, statusName,sum(durationSeconds)/3600 as duration
FROM status
where date_local >=date
and durationSeconds > 0
group by statusId
order by duration desc;
I'm trying to do the same using EF core.
var result = await context.status
.Where(e => e.ShiftdateLocal >= date && e.Durationseconds > 0)
.Select(e => new LiveStatusProductionViewModel
{ StatusId = e.statusId, StatusName = e.statusName, Duration = e.Durationseconds / 3600 })
//.GroupBy(e => e.Duration)
.OrderByDescending(e => e.Duration)
.ToListAsync();
What am I doing wrong? How do I achieve the same result as on mysql?
You have did only half of work, added GroupBy but not added correct projection.
var result = await context.status
.Where(e => e.ShiftdateLocal >= date && e.Durationseconds > 0)
.GroupBy(e => new { e.statusId, e.statusName })
.Select(g => new LiveStatusProductionViewModel
{
StatusId = g.Key.statusId,
StatusName = g.Key.statusName,
Duration = g.Sum(x => x.Durationseconds / 3600)
})
.OrderByDescending(e => e.Duration)
.ToListAsync();
So I've got a table named Summaries, it looks like this
I need to get to sum the latest entries of TotalPieces based on CoveredDate and should be grouped by ServiceCode and queried by month
for example, ServiceCode 'A' has entries on 2020-01-01, 2020-01-02, 2020-01-03, 2020-01-31, 2020-02-01, 2020-02-28, 2020-02-29
and ServiceCode 'B' has entries on 2020-01-01, 2020-01-02, 2020-01-31, 2020-02-20, 2020-02-21,
i need to get the sum based on month, lastest entry on 'A' on January is on 2020-01-31, and 'B' has latest entry on 2020-01-31, I need to sum their 'TotalPieces', so I should get 25 + 25 = 50.
basically i need to do is
Get all the lastest entries based on CoveredDate and month/year
Sum the TotalPieces by ServiceCode
i got a working query, but this is just a workaround because i can't get it right on query.
int sum_totalpieces = 0;
foreach (var serviceCode in service_codes)
{
var totalpieces = _DbContext.ActiveSummaries.Where(acs =>
acs.CoveredDate.Date.Month == query_month
&& acs.CoveredDate.Date.Year == query_year
&& acs.service_codes == serviceCode
)
.OrderByDescending(obd => obd.CoveredDate)
.Take(1)
.Select(s => s.TotalPieces)
.ToList()
.FirstOrDefault();
sum_totalpieces += totalpieces;
}
the service_codes is just a List of string
If you guys could just get rid of the foreach block their and make it services_codes.Contains() on query, or another workaround to make the result faster that would be great. Thanks a lot.
This will do it, but I don't think it will translate to SQL and run at the server:
_DbContext.ActiveSummaries
.Where(b =>
b.CoveredDate >= new DateTime(2020,1,1) &&
b.CoveredDate < new DateTime(2020,2,1) &&
new [] { "A", "B" }.Contains(b.ServiceCode)
)
.GroupBy(g => g.ServiceCode)
.Sum(g => g.OrderByDescending(gb=> gb.CoveredDate).First().TotalPieces);
If you want to do it as a raw SQL for best performance it would look like:
SELECT SUM(totalpieces)
FROM
x
INNER JOIN
(
SELECT servicecode, MAX(covereddate) cd
FROM x
WHERE x.servicecode IN ('A','B') AND covereddate BETWEEN '2020-01-01' AND '2020-01-31'
)y ON x.servicecode=y.servicecode and x.covereddate = y.cd
I want to multiply a value of an specific column considering the user id.
Assume I have a table users with user 1 (id 1) and user 2 (id 2), and a table animals which has name and mensal_cost.
Ok, then I added two animals for user 1 (id 1) and 1 animal for user 2 (id 2)
I want to know how I can using ActiveRecord calculates the mensal_cost income after 3 months increasing the same base value, it means I have to multiply the actual value by 3.
I'm trying something like this:
Animal.where(user_id: ?).sum('3*mensal_cost')
Since I don't know how many users can exist, I must write a call which will list for each user id the amount after 3 months.
Ok, you nearly had it on your own - just the minor details can be like this:
user_ids = [id1, id2]
full_sum = 3 * Animal.where(:user_id => user_ids).sum(:mensal_cost)
Note: don't forget you can multiply by three after summing and it'll be the same as summing each one multiplied by 3 eg
(3 * 2) + (3 * 3) + (3 * 4) == 3 * (2 + 3 + 4)
or you can iterate through the users to get their individual sums like so:
mensal_sums = {}
user_ids = [id1, id2]
user_ids.each do |user_id|
mensal_sums[user_id] = 3 * Animal.where(:user_id => user_id).sum(:mensal_cost)
end
puts mensal_sums
=> {id1 => 63, id2 => 27}
EDIT
and one where you want the user name as well:
mensal_sums = {}
users = User.find([id1, id2])
users.each do |user|
mensal_sums[user.id] = {:user_name => user.name,
:sum => (3 * user.animals.sum(:mensal_cost)) }
end
puts mensal_sums
=> {id1 => {:user_name => "Bob Jones", :sum => 63},
id2 => {:user_name => "cJane Brown", :sum =>27}
}
I just figured out the solution:
Animal.group('user_id').sum('3*mensal_cost')
the group was the key :D
I have two querys:
SELECT LancamentoEntrada.*,
TipoEntrada.descricao AS nome,
Usuario.nome AS obreiro
FROM lancamento_entradas LancamentoEntrada,
tipo_entradas TipoEntrada,
obreiros Obreiro,
usuarios Usuario
WHERE LancamentoEntrada.tipo_entrada_id = TipoEntrada.id
AND TipoEntrada.somar_caixa = 1
AND LancamentoEntrada.obreiro_id = Obreiro.id
AND Usuario.id = Obreiro.usuario_id
AND LancamentoEntrada.data_entrada >= '{$begin}'
AND LancamentoEntrada.data_entrada <= '{$end}'
ORDER BY LancamentoEntrada.data_entrada
And
SELECT LancamentoSaida.*,
TipoSaida.descricao AS nome
FROM lancamento_saidas LancamentoSaida,
tipo_saidas TipoSaida
WHERE LancamentoSaida.tipo_saida_id = TipoSaida.id
AND TipoSaida.somar_caixa = 1
AND LancamentoSaida.data_saida >= '{$begin}'
AND LancamentoSaida.data_saida <= '{$end}'
ORDER BY LancamentoSaida.data_saida
Which generate the follow arrays:
// Query 1
Array(
[0] => Array (
[id] => 3
[tipo_entrada_id] => 1
[data_entrada] => 2012-05-08
[data_vencimento] => 2012-05-08
[obreiro_id] => 2
[valor_pago] => 20.00
[valor_pagar] => 0.01
[observacoes] => TESTE
)
[1] => Array (
[...]
)
)
// Query 2
Array (
[0] => Array (
[id] => 1
[tipo_saida_id] => 1
[data_saida] => 2012-05-08
[data_vencimento] => 2012-05-08
[valor_pago] => 200.00
[observacoes] => tESTE
)
[1] => Array (
[...]
)
)
But, I want to do one query, listing inputs and outputs, how I can acomplish this?
If need more explanation, please, ask-me.
EDIT 1
inputs are generated from first query, output from second.
EDIT 2
The querys need to generate report of financial input/output, so, the first query get all input stored and the second get all output generated, both betwenn from one period. I need to generate a list with all, input and output, ordered by date.
Edit 3
I have done this query, the problem is, how I know when is input and when is output?
Tried ISNULL and CASEs, but not work.
(SELECT LancamentoEntrada.data_entrada AS data,
LancamentoEntrada.data_vencimento AS vencimento,
LancamentoEntrada.valor_pago AS valor,
LancamentoEntrada.observacoes AS observacoes,
TipoEntrada.descricao AS nome
FROM lancamento_entradas LancamentoEntrada,
tipo_entradas TipoEntrada
WHERE LancamentoEntrada.tipo_entrada_id = TipoEntrada.id
AND TipoEntrada.somar_caixa = 1
)
UNION
(SELECT LancamentoSaida.data_saida AS data,
LancamentoSaida.data_vencimento AS vencimento,
LancamentoSaida.valor_pago AS valor,
LancamentoSaida.observacoes AS observacoes,
TipoSaida.descricao AS nome
FROM lancamento_saidas LancamentoSaida,
tipo_saidas TipoSaida
WHERE LancamentoSaida.tipo_saida_id = TipoSaida.id
AND TipoSaida.somar_caixa = 1
)
If the only thing you still need is to identify which records came from which query you just need to add a literal to each query.
( SELECT
'Input' as rec_type,
LancamentoEntrada.data_entrada AS data,
LancamentoEntrada.data_vencimento AS vencimento,
LancamentoEntrada.valor_pago AS valor,
LancamentoEntrada.observacoes AS observacoes,
TipoEntrada.descricao AS nome
FROM lancamento_entradas LancamentoEntrada,
tipo_entradas TipoEntrada
WHERE LancamentoEntrada.tipo_entrada_id = TipoEntrada.id
AND TipoEntrada.somar_caixa = 1
)
UNION ALL
(SELECT
'Output' as rec_type,
LancamentoSaida.data_saida AS data,
LancamentoSaida.data_vencimento AS vencimento,
LancamentoSaida.valor_pago AS valor,
LancamentoSaida.observacoes AS observacoes,
TipoSaida.descricao AS nome
FROM lancamento_saidas LancamentoSaida,
tipo_saidas TipoSaida
WHERE LancamentoSaida.tipo_saida_id = TipoSaida.id
AND TipoSaida.somar_caixa = 1
)
As an aside you'll get better performance if you UNION ALL Since UNION would remove duplicates from the two sets which you won't have in this case.
I have a bunch of incidences in a table that are linked to a supplier
I need to sum the serverity score for those incidences by supplier
So basicly have
supplier1: 500
supplier2: 600
How do I do this?
DataAccess.IncidentRepository().GetItems().Where(i => i.IncidentDate.Year == 2006)
Hope this helps
DataAccess.IncidentRepository().GetItems()
.Where(i => i.IncidentDate.Year == 2006)
.GroupBy(i => i.Supplier)
.Select(pGroup =>
new { Supplier = pGroup.Key,
Score = pGroup.Sum(pArg => pArg.SeverityScore) });