Converting Complicated SQL query to EntityFramework - sql

I'm trying to translate a SQL stored procedure into an EF Core query, but it's proving beyond me.
The SP I'm translating looks like this:
select sale.[CustName] as [Customer Name],
cust.City,
Max(sale.Price) as [MaxPrice],
Avg(sale.Price) as [Average],
sum(case when sale.Price > 0 then 1 else 0 end) as [NumDays]
from SalesRecords as sale
inner join Customers as cust on sale.Acct = cust.AcctNbr
where sale.[Date] between /*Start Date Param*/ and /*End Date Param*/
group by cust.[CustName], cust.City
After some heavy Googling, I've come up with the following EF Query so far:
SalesDataModel salesData =
(from s in Sales
where s.Date >= start && s.Date <= end
join c in Customers on s.Acct equals c.AcctNbr
group s by new { s.Name, c.City } into cg
select new SalesDataModel {
CustName = cg.GetType().Name,
City = cg.GetType().City
MaxBorrowed = (from sa in Sales
select sa.Price).Max(),
Average = (from sa in Sales
select sa.Price).Average(),
NumDays = (from sa in Sales
where sa.Price > 0
select sa.Price).Count()
}).ToListAsync();
...so I think I'm on the right track. So far, I have two questions:
After I group my two datasets into cg, how do I select values from the group to populate SalesDataModel? cg.GetType() doesn't seem to be the way, since the "City" item in my "cust" model isn't found there.
Am I doing my subqueries right? They should be selecting by account number, not from the whole dataset. If I'm not correct, where am I going wrong?

It is simple GroupBy query:
var query =
from s in Sales
where s.Date >= start && s.Date <= end
join c in Customers on s.Acct equals c.AcctNbr
group s by new { s.Name, c.City } into g
select new SalesDataModel
{
CustName = g.Key.Name,
City = g.Key.City,
MaxBorrowed = g.Max(x => x.Price),
Average = g.Average(x => x.Price),
NumDays = g.Sum(x = > .Price > 0 ? 1 : 0)
};

Related

ORACLE SQL "ADD DATE BTW SEVERAL MONTHS

How I will be able to select Date between01JAN2020 and 30 MAY 2020 on the below code?
The below code is for extraction of sales register in oracle, I would like to be able to add on the code a date between ) 01 JAN 2020 and 30 MAY 2020. Any advice on how to handle it?
select distinct 1
,h.trx_number, h.trx_date, bat.name source_name, P.PARTY_NAME,ha.SALES_CHANNEL_CODE
,(select NVL(jrret.source_name, jrret.resource_name)
from jtf_rs_resource_extns_vl jrret
where 1=1
AND jrret.resource_id = rsa.resource_id) Sales_person_NAME -----RSA.NAME putting comments on 14-
nov-2019
,msib.inventory_item_id,
T.NAME TNAME,OL.LINE_ID,OL.ORDERED_ITEM,ORG.ORGANIZATION_NAME,msib.secondary_uom_code,
l.description,l.customer_trx_line_id,h.invoice_currency_code,L.extended_amount,
h.exchange_rate,NVL(l.quantity_invoiced,NVL(QUANTITY_CREDITED,0)) QUANTITY,
L.UOM_CODE,L.UNIT_SELLING_PRICE PRICE,
case when l.extended_amount=(l.extended_amount*nvl(h.exchange_rate,1)) then 0 else l.extended_amount
end Entered_Amount,
(l.extended_amount*nvl(h.exchange_rate,1))Accounted_amount
FROM
RA_CUSTOMER_TRX_ALL H
,RA_CUSTOMER_TRX_LINES_ALL L
,OE_ORDER_LINES_ALL OL
,ORG_ORGANIZATION_DEFINITIONS ORG
,ra_batch_sources_all bat
,mtl_system_items_b msib
, MTL_UOM_CLASS_CONVERSIONS b
,HZ_PARTIES P
,HZ_CUST_ACCOUNTS_ALL HA
,RA_CUST_TRX_TYPES_ALL T,
OE_ORDER_HEADERS_ALL OOHA,
RA_SALESREPS_ALL RSA
WHERE 1=1
AND OL.SALESREP_ID=RSA.SALESREP_ID(+)
AND L.LINE_TYPE = 'LINE'
AND L.CUSTOMER_TRX_ID = H.CUSTOMER_TRX_ID
AND L.INTERFACE_LINE_ATTRIBUTE6 = OL.LINE_ID
and msib.inventory_item_id=b.inventory_item_id(+)
AND ORG.ORGANIZATION_ID = OL.SHIP_FROM_ORG_ID
and bat.batch_source_id = h.batch_source_id
AND P.PARTY_ID = HA.PARTY_ID
and msib.INVENTORY_ITEM_ID=OL.INVENTORY_ITEM_ID
and msib.organization_id = OL.SHIP_FROM_ORG_ID
AND H.BILL_TO_CUSTOMER_ID = CUST_ACCOUNT_ID
and L.INVENTORY_ITEM_ID NOT IN(44717,44723,47722)
AND H.CUST_TRX_TYPE_ID = T.CUST_TRX_TYPE_ID
AND OOHA.HEADER_ID = OL.HEADER_ID
AND OOHA.ORG_ID = OL.ORG_ID
--and H.trx_number='20600200563'
order by trx_date,trx_number
Add below code before order by trx_date,trx_number
First option
H.TRX_DATE >= TO_DATE('01JAN2020','DDMONYYYY') AND H.TRX_DATE <=TO_DATE('30MAY2020','DDMONYYYY');
or
H.TRX_DATE BETWEEN TO_DATE('01JAN2020','DDMONYYYY') AND TO_DATE('30MAY2020','DDMONYYYY');
Second Option
Set session level date format
ALTER SESSION SET NLS_DATE_FORMAT='DDMONYYYY';
AND H.TRX_DATE BETWEEN '01JAN2020' AND '30MAY2020'
or
AND H.TRX_DATE>='01JAN2020' AND H.TRX_DATE<='30MAY2020'

get sum of all rows with id from main query

I need the sum of all positions from one year for every customer.
In the subquery i've hardcoded the customernumber (mark 1) but it needs to be another customernumber for every row.
The values in mark 2 are wrong.
SELECT CustomerNumber AS Kundennummer,
cont.CompanyName AS Firmenname,
(SELECT SUM(SumPositions) FROM OP_Invoices JOIN BAS_Customers ON OP_Invoices.Contact = BAS_Customers.Contact WHERE YEAR(DocumentDate) = 2018 AND BAS_Customers.CustomerNumber = '28673') AS '2018'
FROM BAS_Customers AS cust
JOIN BAS_Contacts AS cont
ON cust.Contact = cont.GUID
Thanks for your help!
If BAS_Customers and BAS_Contacts have a one-to-one relationship, then you should be able to use something like this:
SELECT BAS_Customers.CustomerNumber AS Kundennummer,
cont.CompanyName AS Firmenname,
SUM(SumPositions)
FROM OP_Invoices
JOIN BAS_Customers
ON OP_Invoices.Contact = BAS_Customers.Contact
JOIN BAS_Contacts AS cont
ON cust.Contact = cont.GUID
WHERE YEAR(DocumentDate) = 2018
GROUP BY BAS_Customers.CustomerNumber,
cont.CompanyName
Answering your follow up question in the comments:
SELECT BAS_Customers.CustomerNumber AS Kundennummer,
cont.CompanyName AS Firmenname,
SUM(case when YEAR(DocumentDate) = 2018 then SumPositions else 0 end) AS sum_2018,
SUM(case when YEAR(DocumentDate) = 2019 then SumPositions else 0 end) AS sum_2019
FROM OP_Invoices
JOIN BAS_Customers
ON OP_Invoices.Contact = BAS_Customers.Contact
JOIN BAS_Contacts AS cont
ON cust.Contact = cont.GUID
GROUP BY BAS_Customers.CustomerNumber,
cont.CompanyName

How to subquery - need to calculate new value based on calculated column

The first query should count records - the second query needs to average the counted records. I can't figure out how to use subqueries correctly. This is what I have; obviously the "birds" column doesn't exist since it's created in the subquery, thus my outer query doesn't work:
SELECT
avg(birds)
FROM [FocalAreas].[dbo].[Observation] as o, FocalAreas.dbo.Count as c, FocalAreas.dbo.MonitoringPoint as mp
WHERE EXISTS
(Select
Count(o.ObservationID) as birds
,o.CountID
,mp.MonitoringPointID
FROM [FocalAreas].[dbo].[Observation] as o, FocalAreas.dbo.Count as c, FocalAreas.dbo.MonitoringPoint as mp
where o.CountID = c.CountID
and c.MonitoringPointID = mp.MonitoringPointID
and StateID = 'NE'
and AOUSpeciesID = 1
and Route = 'Focal'
and datepart(year, CountDate) = 2014
group by o.CountID, mp.MonitoringPointID)
I can only guess, because your question could do with some closer description, but maybe you want to do the following:
SELECT
avg(birds)
FROM (Select
Count(o.ObservationID) as birds
,o.CountID
,mp.MonitoringPointID
FROM [FocalAreas].[dbo].[Observation] as o, FocalAreas.dbo.Count as c, FocalAreas.dbo.MonitoringPoint as mp
where o.CountID = c.CountID
and c.MonitoringPointID = mp.MonitoringPointID
and StateID = 'NE'
and AOUSpeciesID = 1
and Route = 'Focal'
and datepart(year, CountDate) = 2014
group by o.CountID, mp.MonitoringPointID) as subq

Query to return all values in a specific table column

The query below returns a somatory of all groups in the year.
How can I return all groups that exists in IND_GRUPO but grouped by the month, if doesn't exist the group for the current month, the name should appear, but the somatory will be 0. All joins should be kept.
SELECT SUM(p.valor), c.nm_grupo, c.cd_grupo, YEAR(p.dt_emissao)
FROM ind_receita p
JOIN ind_equipto o ON p.cd_equipto = o.cd_equipto
JOIN ind_grupo c ON o.cd_grupo = c.cd_grupo
WHERE YEAR(p.dt_emissao) = YEAR(GETDATE())
GROUP BY YEAR(p.dt_emissao), c.nm_grupo, c.cd_grupo
ORDER BY 1 DESC
Try this:
SELECT c.nm_grupo, c.cd_grupo, YEAR(GETDATE()),
(SELECT SUM(p.valor)
FROM ind_receita p
JOIN ind_equipto o ON p.cd_equipto = o.cd_equipto
JOIN ind_grupo c2 ON o.cd_grupo = c2.cd_grupo
WHERE c2.cd_grupo = c.cd_grupo
AND YEAR(p.dt_emissao) = YEAR(GETDATE())) AS valor
FROM ind_grupo c

LightSwitch Linq To Entities query problem !

I'm very new to Linq and Entities Framework. I'm trying to create a WCF RIA Service into a LightSwitch Orders Management application I'm creating. I've already created 7 or 8 queries using Linq (with lot of headaches) but I succeded. Now I need to create a query who gets TotalSales and TotalExpenses by month by using three tables :
DetailsVentes (SaleDetails) composed of : DateOfOrder, Quantity, UnitPrice, Total.... etc
DetailsAchat (PurchaseDetails) composed of the same fields
Charges (Expenses) composed of : DateOfExpense, ExpenseType, Cost....etc
Now I want to have a query that finds the Net Income per month (income=TotalSales-TotalPurchases-TotalExpenses)
I tried this query
Return From od In Me.Context.DetailsVentes
From od2 In Me.Context.DetailsAchats
From od3 In Me.Context.Charges
Group By Month = od.Vente.DateCommande.Month, Year = od.Vente.DateCommande.Year
Into g = Group
Select New TCR With {.Month = Month, .Year = Year,
.MonthYearString = Month & "/" & Year,
.TotalVentes = g.Sum(Function(s) (s.od.PrixUnitaire * s.od.Quantité)),
.TotalAchats = g.Sum(Function(s) (s.od2.PrixAchat * s.od2.Quantité)),
.TotalCharges = g.Sum(Function(s) (s.od3.Cout))}
Where Vente is Sale (Order) and DetailVentes is OrderDetails
Achat is Purchase, and DetailAchat PurchaseDetail
a Charge is an Expense.
The Problem is I got weird results. All values (TotalVentes, TotalAchats, TotalCharges) are multiplicated by 13 !
For eg if I have 10 000 USD totalSales for June 2011, this query returns 130 000 USD !
I'm really stuck 4 days trying to get the correct query.
I repeat I'm new to Linq :p
Thank you very much.
Edit : I tried #Jason advice I did this :
Return From c In Me.Context.Charges
Join v In Me.Context.DetailsVentes On c.DateCharge.Month Equals v.Vente.DateCommande.Month And c.DateCharge.Year Equals v.Vente.DateCommande.Year
Join a In Me.Context.DetailsAchats On c.DateCharge.Month Equals a.Achat.DateCommande.Month And c.DateCharge.Year Equals a.Achat.DateCommande.Year
Group By month = c.DateCharge.Month, Year = c.DateCharge.Year
Into g = Group
Select New TCR With {.Month = month, .Year = Year, .MonthYearString = "", .TotalAchats = g.Sum(Function(c) (c.a.Quantité * c.a.PrixAchat)), .TotalCharges = 45000, .TotalVentes = 250000, .TCRSingle = 0}
And results are still very weird (very high) ! Any exemple I can follow ??
Thank you.
I finally had it works by splitting the query to 3 queries like this :
Dim vt = From od In Me.Context.DetailsVentes
Group By Month = od.Vente.DateCommande.Month, Year = od.Vente.DateCommande.Year
Into g = Group
Select New VentesParMois With {.Month = Month, .Year = Year,
.TotalVentesSingle = g.Sum(Function(od) _
(od.PrixUnitaire * od.Quantité))}
Dim at = From od In Me.Context.DetailsAchats
Group By Month = od.Achat.DateCommande.Month, Year = od.Achat.DateCommande.Year
Into g = Group
Select New AchatsParMois With {.Month = Month, .Year = Year,
.TotalAchatsSingle = g.Sum(Function(od) _
(od.PrixAchat * od.Quantité))}
Dim ct = From od In Me.Context.Charges
Group By Month = od.DateCharge.Month, Year = od.DateCharge.Year
Into g = Group
Select New ChargesParMois With {.Month = Month, .Year = Year,
.TotalChargesSingle = g.Sum(Function(od) _
(od.Montant))}
Dim q = From a In at.AsEnumerable, v In vt.AsEnumerable, c In ct.AsEnumerable
Where a.MonthYear = v.MonthYear AndAlso a.MonthYear = c.MonthYear
Select New TCR With {.Month = a.Month, .Year = a.Year, .TotalAchats = a.TotalAchats, .TotalVentes = v.TotalVentes, .TotalCharges = c.TotalCharges}
Return q.AsQueryable
Thank you very much Jason.
I suspect you want a join somewhere in your query rather than a cartesian product (a join without any join conditions).