Related
I am trying to join three tables in Snowflake, but getting an error on a third one, and not sure if I used a good key :
select
a.CALENDAR_DATE
, a.SALES_DOCUMENT
, a.DOCUMENT_NUMBER_CROSS_BORDER
, *bAUBEL
, *b.NETWR_ship*
, a.Delivery_time
, a.Route_label
, ue.order_ID
from DWHM_MALLGROUP.DM_LOG.SHIPMENTS a
left join (
select
AUBEL,
sum(NETWR) as NETWR_ship
from DWHM_MALLGROUP.SRC_SAP_ERP."2LIS_13_VDITM"
where MATNR in ('10027', '10200', '10402', '10500', '10602', '10603', '10650', '10700')
group by AUBEL
) b
on a.DOCUMENT_NUMBER_CROSS_BORDER = b.AUBEL
where
a.CALENDAR_DATE >= '2020-04-01'
and a.ROUTE in ('CZSK12', 'CZSK21', 'CZSK22', 'CZSK23', 'CZSK24', 'CZSK25', 'CZSK26', 'CZSK27', 'CZSK28', 'CZSK29', 'CZSK30', 'CZSK32', 'CZSK33', 'CZSK34', 'CZSK51', 'CZSK53', 'CZSK54', 'CZSK56')
group by a.CALENDAR_DATE, a.SALES_DOCUMENT, a.DOCUMENT_NUMBER_CROSS_BORDER, b.AUBEL, b.NETWR_ship, a.delivery_time, a.Route_LABEL
left join "DWHM_MALLGROUP"."DM_COMMERCIAL"."UNIT_ECONOMICS" as ue
ON a.SALES_DOCUMENT = ue.order_id
where ue.country = 'SI' and ue.delivery_date >= '2019-08-01'
Your 2nd LEFT JOIN should be moved up to before the WHERE clause:
select
a.CALENDAR_DATE
, a.SALES_DOCUMENT
, a.DOCUMENT_NUMBER_CROSS_BORDER
, b.AUBEL
, b.NETWR_ship
, a.Delivery_time
, a.Route_label
, ue.order_ID
from DWHM_MALLGROUP.DM_LOG.SHIPMENTS a
left join (
select
AUBEL,
sum(NETWR) as NETWR_ship
from DWHM_MALLGROUP.SRC_SAP_ERP."2LIS_13_VDITM"
where MATNR in ('10027', '10200', '10402', '10500', '10602', '10603', '10650', '10700')
group by AUBEL
) b
on a.DOCUMENT_NUMBER_CROSS_BORDER = b.AUBEL
left join "DWHM_MALLGROUP"."DM_COMMERCIAL"."UNIT_ECONOMICS" as ue
ON a.SALES_DOCUMENT = ue.order_id
where
a.CALENDAR_DATE >= '2020-04-01'
and a.ROUTE in ('CZSK12', 'CZSK21', 'CZSK22', 'CZSK23', 'CZSK24', 'CZSK25', 'CZSK26', 'CZSK27', 'CZSK28', 'CZSK29', 'CZSK30', 'CZSK32', 'CZSK33', 'CZSK34', 'CZSK51', 'CZSK53', 'CZSK54', 'CZSK56')
and ue.country = 'SI' and ue.delivery_date >= '2019-08-01'
group by a.CALENDAR_DATE, a.SALES_DOCUMENT, a.DOCUMENT_NUMBER_CROSS_BORDER, b.AUBEL, b.NETWR_ship, a.delivery_time, a.Route_LABEL
NOTE: I am not familiar with the *b that you have in the SELECT clause... it looks like another typo to me, so I removed it.
If you are trying to perform the aggregate (GROUP BY) before the 2nd LEFT JOIN, then you can use a CTE:
WITH CTE_1 AS (
select
a.CALENDAR_DATE
, a.SALES_DOCUMENT
, a.DOCUMENT_NUMBER_CROSS_BORDER
, b.AUBEL
, b.NETWR_ship
, a.Delivery_time
, a.Route_label
from DWHM_MALLGROUP.DM_LOG.SHIPMENTS a
left join (
select
AUBEL,
sum(NETWR) as NETWR_ship
from DWHM_MALLGROUP.SRC_SAP_ERP."2LIS_13_VDITM"
where MATNR in ('10027', '10200', '10402', '10500', '10602', '10603', '10650', '10700')
group by AUBEL
) b
on a.DOCUMENT_NUMBER_CROSS_BORDER = b.AUBEL
where
a.CALENDAR_DATE >= '2020-04-01'
and a.ROUTE in ('CZSK12', 'CZSK21', 'CZSK22', 'CZSK23', 'CZSK24', 'CZSK25', 'CZSK26', 'CZSK27', 'CZSK28', 'CZSK29', 'CZSK30', 'CZSK32', 'CZSK33', 'CZSK34', 'CZSK51', 'CZSK53', 'CZSK54', 'CZSK56')
group by a.CALENDAR_DATE, a.SALES_DOCUMENT, a.DOCUMENT_NUMBER_CROSS_BORDER, b.AUBEL, b.NETWR_ship, a.delivery_time, a.Route_LABEL
) c1
select
c1.CALENDAR_DATE
, c1.SALES_DOCUMENT
, c1.DOCUMENT_NUMBER_CROSS_BORDER
, c1.AUBEL
, c1.NETWR_ship
, c1.Delivery_time
, c1.Route_label
, ue.order_ID
left join "DWHM_MALLGROUP"."DM_COMMERCIAL"."UNIT_ECONOMICS" as ue
ON c1.SALES_DOCUMENT = ue.order_id
and ue.country = 'SI' and ue.delivery_date >= '2019-08-01'
This can (and should, IMO) be cleaned up some more, but I am trying to address the question you asked about joining 3 tables.
There are multiple issues with the SQL.
, *bAUBEL
, *b.NETWR_ship*
we only use * for selecting all fields from a table. For example select A.* , B.col1 from Table_a A , Table_B
sequence for join is
SELECT
FROM Table
JOIN other Table
JOIN Condition
WHERE
GROUP BY
HAVING
Try this SQL
SELECT
a.calendar_date,
a.sales_document,
a.document_number_cross_border,
b.aubel,
b.netwr_ship,
a.delivery_time,
a.route_label,
ue.order_id
FROM
dwhm_mallgroup.dm_log.SHIPMENTS a
left join (
select
AUBEL,
sum(NETWR) as NETWR_ship
from DWHM_MALLGROUP.SRC_SAP_ERP."2LIS_13_VDITM"
where MATNR in ('10027', '10200', '10402', '10500', '10602', '10603', '10650', '10700')
group by AUBEL
) b
on a.DOCUMENT_NUMBER_CROSS_BORDER = b.AUBEL
left join "DWHM_MALLGROUP"."DM_COMMERCIAL"."UNIT_ECONOMICS" as ue ON a.sales_document = ue.order_id
WHERE
a.calendar_date >= '2020-04-01'
AND a.route IN (
'CZSK12',
'CZSK21',
'CZSK22',
'CZSK23',
'CZSK24',
'CZSK25',
'CZSK26',
'CZSK27',
'CZSK28',
'CZSK29',
'CZSK30',
'CZSK32',
'CZSK33',
'CZSK34',
'CZSK51',
'CZSK53',
'CZSK54',
'CZSK56'
)
AND ue.country = 'SI'
AND ue.delivery_date >= '2019-08-01'
GROUP BY
a.calendar_date,
a.sales_document,
a.document_number_cross_border,
b.aubel,
b.netwr_ship,
a.delivery_time,
a.route_label
ue.order_id
I need to run a query to get Data from two views in my SQL Database.
First.
I get required columns from my vw_BillsOfLading then I use left outer join to get Pieces and Weight from my item view where my item's transaction Id = bill of lading id.
here is where I have a challenge.
In most cases, I have multiple item records on each bill of lading. Well, I want to show one record for my bill of lading and get the sum of weight and pieces for each bill of lading record.
Please help me and thank you.
Here is my query
SELECT
b.BillOfLadingNumber
, b.ShipFromCity
, b.ShipFromState
, b.ShipFromZip
, b.DeliveryDate
, b.ShipToCity
, b.ShipToState
, b.ShipToZip
, i.Weight
, i.Pieces
, b.Id
, i.TransactionId
FROM
vw_BillsOfLading b
Left Outer join
vw_Items i
on
i.TransactionId = b.Id
WHERE
BillOfLadingNumber in ('100277' ,'100310' ,'100814' ,'100867' ,'101118' ,'101124' ,'101530' ,'101630' ,'101657' ,'101694' ,'101760' ,'102153' ,'102241' ,'102276' ,'102284')
GROUP BY
b.BillOfLadingNumber
, b.ShipFromCity
, b.ShipFromState
, b.ShipFromZip
, b.DeliveryDate
, b.ShipToCity
, b.ShipToState
, b.ShipToZip
, i.Weight
, i.Pieces
, b.Id
, i.TransactionId
Try this (shooting from the hip here - I don't have a SQL Server instance on this machine):
SELECT b.BillOfLadingNumber, b.ShipFromCity, b.ShipFromState, b.ShipFromZip, b.DeliveryDate, b.ShipToCity, b.ShipToState, b.ShipToZip,
Sum(i.Weight) as Total_Weight,
Sum(i.Pieces) as Piece_Count
FROM vw_BillsOfLading b
Left Outer join vw_Items i
on i.TransactionId = b.Id
WHERE BillOfLadingNumber in ('100277','100310','100814','100867','101118','101124','101530','101630','101657','101694','101760','102153','102241','102276','102284')
GROUP BY b.BillOfLadingNumber,b.ShipFromCity, b.ShipFromState, b.ShipFromZip, b.DeliveryDate, b.ShipToCity, b.ShipToState, b.ShipToZip
Just remove the i.weight and i.pieces from your grouping:
select b.billofladingnumber, b.shipfromcity, b.shipfromstate, b.shipfromzip, b.deliverydate, b.shiptocity, b.shiptostate, b.shiptozip, , b.id, i.transactionid, sum(i.weight) weight, sum(i.pieces) pieces
from vw_billsoflading b left outer join vw_items i on i.transactionid = b.id
where billofladingnumber in ('100277','100310','100814','100867','101118','101124','101530','101630','101657','101694','101760','102153','102241','102276','102284')
group by b.billofladingnumber, b.shipfromcity, b.shipfromstate, b.shipfromzip, b.deliverydate, b.shiptocity, b.shiptostate, b.shiptozip, , b.id, i.transactionid
Sum is your friend:
SELECT
b.BillOfLadingNumber
, b.ShipFromCity
, b.ShipFromState
, b.ShipFromZip
, b.DeliveryDate
, b.ShipToCity
, b.ShipToState
, b.ShipToZip
, i.Weight
, i.Pieces
, b.Id
, i.TransactionId
FROM
vw_BillsOfLading b
Left Outer join
vw_Items i
on
i.TransactionId = b.Id
WHERE
BillOfLadingNumber in ('100277' ,'100310' ,'100814' ,'100867' ,'101118' ,'101124' ,'101530' ,'101630' ,'101657' ,'101694' ,'101760' ,'102153' ,'102241' ,'102276' ,'102284')
GROUP BY
b.BillOfLadingNumber
, b.ShipFromCity
, b.ShipFromState
, b.ShipFromZip
, b.DeliveryDate
, b.ShipToCity
, b.ShipToState
, b.ShipToZip
, i.Weight
, i.Pieces
, b.Id
, i.TransactionId
I have the following queries:
select AccountId
into #liveCustomers
from AccountExtensionBase where New_duos_group not in ('T053','T054')
and New_AccountStage = 7
select AccountId
into #customerWhoLeft
from New_marketmessagein as a
inner join AccountExtensionBase as b on a.new_accountmminid = b.AccountId
where New_MessageTypeCode = '105L'
and a.New_EffectiveFromDate > '30 jun 2016'
and b.New_duos_group not in ('T053','T054')
select
accountid
, New_MPRNNumber
, New_duos_group
, New_CommercialAgreementDayRate
, New_CommercialAgreementNightRate
, New_CommercialAgreementHeatRate
, New_Tariffpriceagreedatsignup
, New_Tariffname
into
#monthCustomers
from
AccountExtensionBase
where
AccountId in (select * from #customerWhoLeft)
or
AccountId in (select * from #liveCustomers)
I now wish to join a table called usagefactorExtensionBase and join only the row containing the most recent read date but when I try to join this to my table of 4985 monthly customers I get like 106,813 rows using this code so I think my join or methodology has gone awry, can someone please help me correct the error so I display the list of monthCustomers plus the read details of their most recent read.
Attempting:
select
accountid
, New_MPRNNumber
, New_duos_group
, New_CommercialAgreementDayRate
, New_CommercialAgreementNightRate
, New_CommercialAgreementHeatRate
, New_Tariffpriceagreedatsignup
, New_Tariffname
, max(b.New_EffectiveFromDate)
, b.New_ActualUsageFactor
, b.New_EstimatedUseage
from
#monthCustomers as a
left join
New_marketmessageinusagefactorExtensionBase as b
on a.AccountId = b.new_accountmmusagefactorid
group by
accountid
, New_MPRNNumber
, New_duos_group
, New_CommercialAgreementDayRate
, New_CommercialAgreementNightRate
, New_CommercialAgreementHeatRate
, New_Tariffpriceagreedatsignup
, New_Tariffname
, b.New_ActualUsageFactor
, b.New_EstimatedUseage
try this,
SELECT
accountid,
New_MPRNNumber,
New_duos_group,
New_CommercialAgreementDayRate,
New_CommercialAgreementNightRate,
New_CommercialAgreementHeatRate,
New_Tariffpriceagreedatsignup,
New_Tariffname,
b.New_EffectiveFromDate,
b.New_ActualUsageFactor,
b.New_EstimatedUseage
FROM #monthCustomers AS a
-- Get only max date rows for each AccountID
LEFT JOIN( SELECT t1.*
FROM New_marketmessageinusagefactorExtensionBase AS t1
INNER JOIN ( SELECT new_accountmmusagefactorid, MAX(New_EffectiveFromDate) AS New_EffectiveFromDate_Max
FROM New_marketmessageinusagefactorExtensionBase
GROUP BY new_accountmmusagefactorid
) AS t2 ON t2.new_accountmmusagefactorid = t1.new_accountmmusagefactorid
AND t2.New_EffectiveFromDate_Max = t1.New_EffectiveFromDate
)AS b
ON a.AccountId = b.new_accountmmusagefactorid
there might be rows with same date, try below if is works,
SELECT
accountid,
New_MPRNNumber,
New_duos_group,
New_CommercialAgreementDayRate,
New_CommercialAgreementNightRate,
New_CommercialAgreementHeatRate,
New_Tariffpriceagreedatsignup,
New_Tariffname,
b.New_EffectiveFromDate,
b.New_ActualUsageFactor,
b.New_EstimatedUseage
FROM #monthCustomers AS a
-- Get only max date rows for each AccountID
LEFT JOIN( SELECT New_MPRNNumber,
New_duos_group,
New_CommercialAgreementDayRate,
New_CommercialAgreementNightRate,
New_CommercialAgreementHeatRate,
New_Tariffpriceagreedatsignup,
New_Tariffname,
MAX(New_EffectiveFromDate) AS New_EffectiveFromDate,
New_ActualUsageFactor,
New_EstimatedUseage
FROM New_marketmessageinusagefactorExtensionBase AS t1
GROUP BY
New_MPRNNumber,
New_duos_group,
New_CommercialAgreementDayRate,
New_CommercialAgreementNightRate,
New_CommercialAgreementHeatRate,
New_Tariffpriceagreedatsignup,
New_Tariffname,
New_ActualUsageFactor,
New_EstimatedUseage
)AS b
ON a.AccountId = b.new_accountmmusagefactorid
I have a query that I need to add a column to. I can find many similar examples but nothing quite works right for this situation. There could be infinite CategoryIDs and I need to add the Sum(IsOutage) grouped by CategoryID. This is some sample data:
and here is the closest I have to getting it to work:
SELECT c.CategoryID
, c.Name
, COUNT(i.IssueID) AS TotalIssues
, AVG(DATEDIFF(MI, i.StartDate, i.ResolvedDate)) AS AvgDuration
,(Select COUNT(h.IssueID) From dbo.hdIssues AS h Where h.CategoryID = i.CategoryID AND IsOutage = 1 ) AS TotalOutages
FROM dbo.hdCategories AS c INNER JOIN
dbo.hdIssues AS i ON c.CategoryID = i.CategoryID
WHERE (i.StatusID = 3)
GROUP BY c.CategoryID, c.Name, TotalOutages
Am I close? Please advise and thanx in advance
EDIT: This is a mock up of what the result should look like:
If i correctly understand your needs this query should give you desired result:
SELECT x.* ,
y.SumIsOutage
FROM (SELECT c.CategoryID ,
c.Name ,
COUNT(i.IssueID) AS TotalIssues ,
AVG(DATEDIFF(MI, i.StartDate, i.ResolvedDate)) AS AvgDuration
FROM dbo.hdCategories AS c
INNER JOIN dbo.hdIssues AS i ON c.CategoryID = i.CategoryID
WHERE (i.StatusID = 3)
GROUP BY c.CategoryID, c.Name ) x
LEFT JOIN (SELECT DISTINCT i.CategoryId,
SUM(CONVERT(INT,i.isOutage)) OVER (PARTITION BY i.CategoryId) AS SumIsOutage
FROM dbo.hdIssues AS i ) y
ON x.CategoryId = y.CategoryId
You can use conditional aggregation. Also, you shouldn't group by totaloutages
SELECT
c.CategoryID
, c.Name
, COUNT(i.IssueID) AS TotalIssues
, AVG(DATEDIFF(MI, i.StartDate, i.ResolvedDate)) AS AvgDuration
,sum(case when IsOutage = 1 then 1 else 0 end) AS TotalOutages
FROM dbo.hdCategories AS c INNER JOIN
dbo.hdIssues AS i ON c.CategoryID = i.CategoryID
WHERE i.StatusID = 3
GROUP BY c.CategoryID, c.Name
You don't need another subquery for this count. Just count the rows that you're interested in:
COUNT(CASE WHEN i.IsOutage = 1 THEN 1 END)
In the context of your query:
SELECT
c.CategoryID
, c.Name
, COUNT(i.IssueID) AS TotalIssues
, AVG(DATEDIFF(MI, i.StartDate, i.ResolvedDate)) AS AvgDuration
, COUNT(CASE WHEN CONVERT(INT, i.IsOutage) = 1 THEN 1 END) AS TotalOutages
FROM
dbo.hdCategories AS c
INNER JOIN
dbo.hdIssues AS i
ON c.CategoryID = i.CategoryID
WHERE
i.StatusID = 3
GROUP BY
c.CategoryID
, c.Name
SELECT TOP (100) PERCENT MsgCount.msgcount
, c.userid
, c.aspnet_guid
, c.fname
, c.lname
, c.profileimagepath
, c.profilealbumid
, p1.msgdate
, SUBSTRING(p1.msgcontent, 0, 50) AS msgcontent
, p1.msgtouser
FROM dbo.userprofile AS c
INNER JOIN dbo.usermessages AS p1
ON c.userid = p1.msgfromuser
LEFT OUTER JOIN dbo.usermessages AS p2
ON c.userid = p2.msgfromuser
AND (p1.msgdate < p2.msgdate
OR p1.msgdate = p2.msgdate
AND p1.msgid < p2.msgid)
LEFT OUTER JOIN
(
SELECT msgfromuser
, COUNT(msgfromuser) AS msgcount
FROM dbo.usermessages
GROUP BY msgfromuser
) AS MsgCount
ON MsgCount.msgfromuser = p1.msgfromuser
WHERE (p2.msgid IS NULL)
ORDER BY p2.msgdate DESC
Maybe try ordering by:
p1.msgdate
instead of:
p2.msgdate
This is only a suggestion :)
I am not sure what the data looks like in your table, but because you have a left outer join to p2, I am assuming that you are expecting that sometime there is not a value and p2.msgdate is null. By ordering only by p2.msgdate ( a potentially null column ) you will not get the consistent results that you would get by ordering by a column that always has a value in it. Perhaps ordering by p1.msgdate, or even coalesce(p2.msgdate,p1.msgdate) might give you more consistent results.
SELECT TOP (100) PERCENT MsgCount.msgcount
, c.userid
, c.aspnet_guid
, c.fname
, c.lname
, c.profileimagepath
, c.profilealbumid
, p1.msgdate
, SUBSTRING(p1.msgcontent, 0, 50) AS msgcontent
, p1.msgtouser
FROM dbo.userprofile AS c
INNER JOIN dbo.usermessages AS p1
ON c.userid = p1.msgfromuser
LEFT OUTER JOIN dbo.usermessages AS p2
ON c.userid = p2.msgfromuser
AND (p1.msgdate < p2.msgdate
OR p1.msgdate = p2.msgdate
AND p1.msgid < p2.msgid)
LEFT OUTER JOIN
(
SELECT msgfromuser
, COUNT(msgfromuser) AS msgcount
FROM dbo.usermessages
GROUP BY msgfromuser
) AS MsgCount
ON MsgCount.msgfromuser = p1.msgfromuser
WHERE (p2.msgid IS NULL)
ORDER BY p1.msgdate, p2.msgdate DESC