How can we Group BY a column in SQL with inner join? - sql

I will attach a screenshot, please look at it:
In this I need to get sum of the [LOCAL CURRENCY] according to each each Branch Name
SELECT
BR.BranchName [BRANCH NAME],
PDS.ProductName [CURRENCY],
SUM(FCBD.Quantity) [QUANTITY],
FCBD.BuyingRate [RATE],
SUM(CONVERT(DECIMAL(12, 3), (FCBD.Quantity * FCBD.BuyingRate))) [LOCAL CURRENCY],
0 [TOTAL]
FROM
ALX_FCBuy FCB
INNER JOIN
ALX_FCBuyDetails FCBD ON FCB.FCBuyID = FCBD.FCBuyID
INNER JOIN
ALX_Branches BR ON FCB.BranchID = BR.BranchID
INNER JOIN
ALX_Products PDS ON FCBD.ProductID = PDS.ProductID
GROUP BY
BR.BranchName, FCBD.ProductID, PDS.ProductName, FCBD.BuyingRate

SELECT
BR.BranchName [BRANCH NAME],
PDS.ProductName [CURRENCY],
SUM(FCBD.Quantity) [QUANTITY],
FCBD.BuyingRate [RATE],
SUM(CONVERT(DECIMAL(12, 3), (FCBD.Quantity * FCBD.BuyingRate))) [LOCAL CURRENCY],
SUM(SUM(CONVERT(DECIMAL(12, 3), FCBD.Quantity * FCBD.BuyingRate))) OVER (PARTITION BY BR.BranchName) [TOTAL]
FROM
ALX_FCBuy FCB
INNER JOIN
ALX_FCBuyDetails FCBD ON FCB.FCBuyID = FCBD.FCBuyID
INNER JOIN
ALX_Branches BR ON FCB.BranchID = BR.BranchID
INNER JOIN
ALX_Products PDS ON FCBD.ProductID = PDS.ProductID
GROUP BY
BR.BranchName, FCBD.ProductID, PDS.ProductName, FCBD.BuyingRate

If you need the sum for each branch, then only put that in the SELECT and GROUP BY:
SELECT BR.BranchName [BRANCH NAME],
SUM(CONVERT(DECIMAL(12, 3), FCBD.Quantity * FCBD.BuyingRate)) [LOCAL CURRENCY],
FROM ALX_FCBuy FCB INNER JOIN
ALX_FCBuyDetails FCBD
ON FCB.FCBuyID = FCBD.FCBuyID INNER JOIN
ALX_Branches BR
ON FCB.BranchID = BR.BranchID INNER JOIN
ALX_Products PDS
ON FCBD.ProductID = PDS.ProductID
GROUP BY BR.BranchName;
If you want an additional column in your existing result set, then the calculation would use window functions:
SELECT . . .
SUM(SUM(CONVERT(DECIMAL(12, 3), FCBD.Quantity * FCBD.BuyingRate))) OVER (PARTITION BY BR.BranchName) as Total
. . .

Related

Only display the day with the max profit per store

Only display the day with the max profit per store in SQL Server
For example only {Monday 5929.00 DARIEN BRONX GOODS} should only show for DARIEN BRONX GOODS
What I have so far.
select
Dim_Date.WeekDayName,
sum(dbo.DIM_PRODUCT.PRODUCT_PRICE) as [Total Profit],
DIM_D_STORE.STORE_NAME as [Store Name]
from
dbo.DIM_EMPLOYEE
inner join dbo.S_ORDER_FACT on
dbo.DIM_EMPLOYEE.EMPLOYEE_ID = dbo.S_ORDER_FACT.ORDER_EMPLOYEEID
inner join dbo.DIM_CUSTOMER on
dbo.DIM_CUSTOMER.CUSTOMERID = dbo.S_ORDER_FACT.ORDER_CUSTOMERID
inner join dbo.Dim_Date on
dbo.Dim_Date.DateKey = dbo.S_ORDER_FACT.ORDER_DATEID
inner join dbo.DIM_D_STORE on
dbo.DIM_D_STORE.STOREID = dbo.S_ORDER_FACT.ORDER_STOREID
inner join dbo.DIM_PRODUCT on
dbo.DIM_PRODUCT.PRODUCTID = dbo.S_ORDER_FACT.ORDER_PRODUCTID
group by
DIM_D_STORE.STORE_NAME,
Dim_Date.WeekDayName
order by
DIM_D_STORE.STORE_NAME,
[Total Profit] desc
offset 0 rows ;
[Output in image ]
here is one way using window functions:
select * from (
select
Dim_Date.WeekDayName,
sum(dbo.DIM_PRODUCT.PRODUCT_PRICE) as [Total Profit],
DIM_D_STORE.STORE_NAME as [Store Name],
rank() over (partition by STORE_NAME order by sum(dbo.DIM_PRODUCT.PRODUCT_PRICE) desc) rn
from
dbo.DIM_EMPLOYEE
inner join dbo.S_ORDER_FACT on
dbo.DIM_EMPLOYEE.EMPLOYEE_ID = dbo.S_ORDER_FACT.ORDER_EMPLOYEEID
inner join dbo.DIM_CUSTOMER on
dbo.DIM_CUSTOMER.CUSTOMERID = dbo.S_ORDER_FACT.ORDER_CUSTOMERID
inner join dbo.Dim_Date on
dbo.Dim_Date.DateKey = dbo.S_ORDER_FACT.ORDER_DATEID
inner join dbo.DIM_D_STORE on
dbo.DIM_D_STORE.STOREID = dbo.S_ORDER_FACT.ORDER_STOREID
inner join dbo.DIM_PRODUCT on
dbo.DIM_PRODUCT.PRODUCTID = dbo.S_ORDER_FACT.ORDER_PRODUCTID
group by
DIM_D_STORE.STORE_NAME,
Dim_Date.WeekDayName
) table where rn = 1
Wouldn't Top 1 do the job for selecting highest profit?
select Top 1,
Dim_Date.WeekDayName,
sum(dbo.DIM_PRODUCT.PRODUCT_PRICE) as [Total Profit],
DIM_D_STORE.STORE_NAME as [Store Name]
from
dbo.DIM_EMPLOYEE
inner join dbo.S_ORDER_FACT on
dbo.DIM_EMPLOYEE.EMPLOYEE_ID = dbo.S_ORDER_FACT.ORDER_EMPLOYEEID
inner join dbo.DIM_CUSTOMER on
dbo.DIM_CUSTOMER.CUSTOMERID = dbo.S_ORDER_FACT.ORDER_CUSTOMERID
inner join dbo.Dim_Date on
dbo.Dim_Date.DateKey = dbo.S_ORDER_FACT.ORDER_DATEID
inner join dbo.DIM_D_STORE on
dbo.DIM_D_STORE.STOREID = dbo.S_ORDER_FACT.ORDER_STOREID
inner join dbo.DIM_PRODUCT on
dbo.DIM_PRODUCT.PRODUCTID = dbo.S_ORDER_FACT.ORDER_PRODUCTID
group by
DIM_D_STORE.STORE_NAME,
Dim_Date.WeekDayName
order by
[Total Profit] desc,
DIM_D_STORE.STORE_NAME

Join results of 3 queries

i have 3 worked queries, but i don't know how to combin them in one query.
TABLES :
------------------ -------------------------- -----------------
PIECE MCARTEFIDENT MCARTEFIDLIG
------------------ -------------------------- -----------------
ET_LIBELLE : Store MFC_ETABLISSEMENT : STORE MFL_ETABLISSEMENT
GP_NUMERO : TICKET MFC_VALDISPOTHEO MFL_NBPASSAGEAPRES
------------------- --------------------------
--QUERY 1
select [et_libelle] AS [STORE NAME],COUNT([GP_NUMERO])
FROM PIECE
LEFT OUTER JOIN ETABLISS ET1 ON gp_etablissement=ET1.ET_ETABLISSEMENT
GROUP BY et_libelle
--QUERY 2
SELECT MFC_ETABLISSEMENT as [STORE NAME], COUNT (MFC_VALDISPOTHEO)
FROM MCARTEFIDENT
LEFT OUTER JOIN ETABLISS ET2 ON MFC_ETABLISSEMENT=ET2.ET_ETABLISSEMENT
GROUP BY MFC_ETABLISSEMENT
--QUERY 3
SELECT MFL_ETABLISSEMENT AS [STORE NAME], MFL_NBPASSAGEAPRES
FROM MCARTEFIDLIG
LEFT OUTER JOIN ETABLISS ET3 ON MFL_ETABLISSEMENT=ET3.ET_ETABLISSEMENT
GROUP BY MFL_ETABLISSEMENT
columns should be the result after combine :
[et_libelle] (Query 1),
COUNT([GP_NUMERO]) (Query 1),
COUNT([GP_NUMERO]) (Query 2),
MFL_NBPASSAGEAPRES (Query 3)
you could use your 3 queries as subqiery and join
select a.[STORE NAME], a.count_gp_numero, b.count_mfc_valdispotheo, c.MFL_NBPASSAGEAPRES
from (
select [et_libelle] AS [STORE NAME], COUNT([GP_NUMERO]) count_gp_numero
FROM PIECE
LEFT OUTER JOIN ETABLISS ET1 ON gp_etablissement=ET1.ET_ETABLISSEMENT
GROUP BY et_libelle
) a
left join (
SELECT MFC_ETABLISSEMENT as [STORE NAME], COUNT(MFC_VALDISPOTHEO) b.count_mfc_valdispotheo
FROM MCARTEFIDENT
LEFT OUTER JOIN ETABLISS ET2 ON MFC_ETABLISSEMENT=ET2.ET_ETABLISSEMENT
GROUP BY MFC_ETABLISSEMENT
) b on a.[STORE NAME] = b.[STORE NAME]
left join (
SELECT MFL_ETABLISSEMENT AS [STORE NAME], MFL_NBPASSAGEAPRES
FROM MCARTEFIDLIG
LEFT OUTER JOIN ETABLISS ET3 ON MFL_ETABLISSEMENT=ET3.ET_ETABLISSEMENT
GROUP BY MFL_ETABLISSEMENT
) c on a.[STORE NAME] = c.[STORE NAME]
If I had to speculate, my guess would be that you want:
select e.*,
(select count(*)
from piece p
where p.gp_etablissement = e.et_etablissement
),
(select count(*)
from MCARTEFIDENT mfc
where mfc.MFC_ETABLISSEMENT = e.et_etablissement
),
(select MFL_NBPASSAGEAPRES -- perhaps a `sum()` here???
from MCARTEFIDENT mfl
where mfl.MFL_ETABLISSEMENT = e.et_etablissement
)
from etabliss e;

SQL Server where clause order count > 0

I have a query that works but returns all students, whether they place orders or not. I just want those with orders. The query works fine until I add the where clause. How can I properly write this?
SELECT top 100 percent s.id, s.fname as [First Name], s.lname as [Last Name],
(select count(student_id) from orderX x where x.student_id=s.id) as [Order Count],
(select sum(no_attendees) from orderX x where x.student_id=s.id) as [Attendees / Participants],
(select sum(eventHours) from orderX x where x.student_id=s.id) as [Event Hours],
oc1.text as [Occupation 1], oc2.text as [Occupation 2],
oc3.text as [Occupation 3], s.OccupationOther, s.dateGraduated, s.organization, s.city, s.zip, s.st, s.county,
aud.text as [Preferred Audience], pts.text as [Plans to Share], mr.text as [Main Reason]
FROM student s
left join occupation1 oc1 on s.Occupation1 = oc1.id
left join occupation2 oc2 on s.Occupation2 = oc2.id
left join occupation3 oc3 on s.Occupation3 = oc3.id
left join audience aud on s.audience = aud.id
left join PlanToShare pts on s.PlanToShare = pts.id
left join mainReason mr on s.mainReason = mr.id
where [Order Count] > 0
For starters you could replace your where clause by
where (select count(student_id) from orderX x where x.student_id=s.id) > 0
I think no correlation needed here. Find all the aggregates in subquery and "inner" join it (inner because you are anyways going to filter out zero count rows)
select top 100 percent s.id,
s.fname as [First Name],
s.lname as [Last Name],
x.order_count as [Order Count],
x.attendess_participants as [Attendees / Participants],
x.eventHours as [Event Hours],
oc1.text as [Occupation 1],
oc2.text as [Occupation 2],
oc3.text as [Occupation 3],
s.OccupationOther,
s.dateGraduated,
s.organization,
s.city,
s.zip,
s.st,
s.county,
aud.text as [Preferred Audience],
pts.text as [Plans to Share],
mr.text as [Main Reason]
from student s
left join occupation1 oc1 on s.Occupation1 = oc1.id
left join occupation1 oc2 on s.Occupation2 = oc2.id
left join occupation1 oc3 on s.Occupation3 = oc3.id
left join audience aud on s.audience = aud.id
left join PlanToShare pts on s.PlanToShare = pts.id
left join mainReason mr on s.mainReason = mr.id
inner join (
select student_id,
count(*) as order_count,
sum(no_attendees) as attendess_participants,
sum(eventHours) as event_hours
from orderX x
group by student_id
) x on x.student_id = s.id;
You will have to use
where (select count(student_id) from orderX x where x.student_id=s.id)
instead. In sql-server you cannot use aliases in where clauses.
You cannot use a column alias ([Order count]) in the WHERE clause. Either repeat the
(select count(student_id) from orderX x where x.student_id=s.id)
in the WHERE clause as
WHERE (select count(student_id) from orderX x where x.student_id=s.id) > 0
or use a cte.

SQL: How do I show all Items in Inventory and Sum sales of items sold in a time period?

I am trying to find all items on hand from #Supplier_ID and summarize any sales since #Begin_Date. What is returned are all items on hand that have never been sold and those sold since #Begin_Date. Items on hand that were sold before #Begin_Date are excluded from the results. How do I fix that?
I am using SQL Server 2012 and SSRS v3.
SELECT DISTINCT
inventory_supplier.supplier_id AS [Supp ID],
address.name AS Supplier,
inv_loc.location_id AS [Inventory Loc ID],
inv_mast.item_id AS [Item ID],
inv_mast.item_desc AS [Item Desc],
inv_loc.qty_on_hand AS QOH,
inv_loc.moving_average_cost AS MAC,
invoice_line.qty_shipped,
invoice_hdr.customer_id AS [Customer ID],
invoice_hdr.bill2_name AS Customer,
oe_line.source_loc_id AS [Sales Source Loc]
FROM
inventory_supplier
INNER JOIN
inv_mast ON inventory_supplier.inv_mast_uid = inv_mast.inv_mast_uid
INNER JOIN
address ON inventory_supplier.supplier_id = address.id
FULL OUTER JOIN
invoice_line ON inv_mast.inv_mast_uid = invoice_line.inv_mast_uid
FULL OUTER JOIN
inv_loc ON inv_mast.inv_mast_uid = inv_loc.inv_mast_uid
FULL OUTER JOIN
invoice_hdr ON invoice_line.invoice_no = invoice_hdr.invoice_no
FULL OUTER JOIN
oe_line ON invoice_hdr.order_no = oe_line.order_no
AND invoice_line.inv_mast_uid = oe_line.inv_mast_uid
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date
OR invoice_hdr.invoice_date IS NULL)
AND (inv_loc.qty_on_hand > 0)
ORDER BY
[Item ID], [Inventory Loc ID], [Customer ID], [Sales Source Loc]
You could move your invoice_hdr.invoice_date >= #Begin_Date to your join statement
FULL OUTER JOIN
invoice_hdr ON invoice_line.invoice_no = invoice_hdr.invoice_no
AND invoice_hdr.invoice_date >= #Begin_Date
Don't see a lot of FULL OUTER JOINs. Sure you don't want LEFT JOIN here?
You might want to separate out the Invoice information from the Inventory information into a subquery, and LEFT JOIN to the Invoice information.
SELECT DISTINCT
inventory_supplier.supplier_id AS [Supp ID],
address.name AS Supplier,
inv_loc.location_id AS [Inventory Loc ID],
inv_mast.item_id AS [Item ID],
inv_mast.item_desc AS [Item Desc],
inv_loc.qty_on_hand AS QOH,
inv_loc.moving_average_cost AS MAC,
invoices.qty_shipped,
invoices.customer_id AS [Customer ID],
invoices.bill2_name AS Customer,
invoices.source_loc_id AS [Sales Source Loc]
FROM
inventory_supplier
INNER JOIN
inv_mast ON inventory_supplier.inv_mast_uid = inv_mast.inv_mast_uid
INNER JOIN
address ON inventory_supplier.supplier_id = address.id
INNER JOIN
inv_loc ON inv_mast.inv_mast_uid = inv_loc.inv_mast_uid
LEFT OUTER JOIN
(SELECT
invoice_line.inv_mast_uid,
invoice_line.qty_shipped,
invoice_hdr.customer_id,
invoice_hdr.bill2_name,
oe_line.source_loc_id
FROM
invoice_line
INNER JOIN
invoice_hdr ON invoice_line.invoice_no = invoice_hdr.invoice_no
INNER JOIN
oe_line ON invoice_hdr.order_no = oe_line.order_no
AND invoice_line.inv_mast_uid = oe_line.inv_mast_uid
WHERE
invoice_hdr.invoice_date >= #Begin_Date
) invoices ON invoices.inv_mast_uid = inv_mast.inv_mast_uid
WHERE
inventory_supplier.supplier_id = #Supplier_ID
AND inv_loc.qty_on_hand > 0
ORDER BY
[Item ID], [Inventory Loc ID], [Customer ID], [Sales Source Loc]
Try changing
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date
OR invoice_hdr.invoice_date IS NULL)
AND (inv_loc.qty_on_hand > 0)
to
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date)
AND (inv_loc.qty_on_hand > 0)
The problem is because you are including dates, invoice_hdr.invoice_date that are NULL in the WHERE clause. Simply remove it:
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date)
AND (inv_loc.qty_on_hand > 0)

SQL Query Second sum column squaring results

If I run 2 queries separately I get results like this..
select A.ACTNUMST, sum(B.EXTDCOST) as [IV Total]
from GL00105 A
INNER JOIN SEE30303 B on A.ACTINDX = B.IVIVINDX
group by A.ACTNUMST
Results -
Account No IV Total
2101-00-137 2033.60
4101-00-137 83765.86
6101-00-137 301984.23
Second Query
select A.ACTNUMST as [Account No], SUM(C.PERDBLNC) as [GL Total]
from GL00105 A
LEFT JOIN GL10110 C on A.ACTINDX = C.ACTINDX
group by A.ACTNUMST
Results -
Account No GL Total
2101-00-137 2033.60
4101-00-137 83765.86
6101-00-137 302656.23
I want to be able to join both results together to compare but I believe it is repeating the sum for each line in the GL total and then summing it again, it comes out with large numbers like -
select A.ACTNUMST as [Account No], sum(B.EXTDCOST) as [IV Total], SUM(C.PERDBLNC) as [GL Total]
from GL00105 A
INNER JOIN SEE30303 B on A.ACTINDX = B.IVIVINDX
LEFT JOIN GL10110 C on A.ACTINDX = C.ACTINDX
group by A.ACTNUMST
Results -
Account No IV Total GL Total
2101-00-137 2033.60 14235.20
4101-00-137 83765.86 116350696.20
6101-00-137 301984.23 1612897825.84
When it should be
Results -
Account No IV Total GL Total
2101-00-137 2033.60 2033.60
4101-00-137 83765.86 83765.86
6101-00-137 301984.23 302656.23
Please advise how to use the sum function to get the correct results.
Do you want something like this? Please check and comment if this is not what is expected.
Also please rectify any syntax errors.
SELECT T1.[Account No], T1.[IV Total], T2.[GL Total] FROM
(
select A.ACTNUMST as [Account No], sum(B.EXTDCOST) as [IV Total]
from GL00105 A
INNER JOIN SEE30303 B on A.ACTINDX = B.IVIVINDX
group by A.ACTNUMST
) T1
INNER JOIN
(
select A.ACTNUMST as [Account No], SUM(C.PERDBLNC) as [GL Total]
from GL00105 A
LEFT JOIN GL10110 C on A.ACTINDX = C.ACTINDX
group by A.ACTNUMST
) T2
ON T1.[Account No] = T2.[Account No]
Hope this helps
this can be done with the multiple cte also
with IVTotal as
(
select A.ACTNUMST, sum(B.EXTDCOST) as [IV Total]
from GL00105 A
INNER JOIN SEE30303 B
on A.ACTINDX = B.IVIVINDX
group by A.ACTNUMST
),
GLTotal as
(
select A.ACTNUMST as [Account No], SUM(C.PERDBLNC) as [GL Total]
from GL00105 A
LEFT JOIN GL10110 C
on A.ACTINDX = C.ACTINDX
group by A.ACTNUMST
)
select a.*,b.[GL Total]
from IVTotal a ,GLTotal b
where a.ACTNUMST = b.aCTNUMST