Pivot With Grouping? - tsql

I am building a query for a SSRS Report and I have a pivot for locations and quantity. I am getting two rows one for each location but when I pivot I want the end result to be one row.
SELECT *
FROM ( SELECT DISTINCT ItemNmbr ,
ITEMDESC ,
Location ,
QtyOnhand ,
QtyOnOrder ,
QtyBackordered ,
TotalInventory ,
EXTDCOST ,
InventoryValue
FROM #ssrsFinal
) AS p PIVOT
(SUM(QTYOnHand) FOR Location IN ( Loc1, Loc2, HUB, INLAND, Loc, [OLD Loc],[IN TRANSIT] )
) AS pvt;
My result is two rows, How do i get it to just one?
I have tried inserting the pivot results into a temp table and then grouping but it does not carry over the locations in the select.
Results before the Pivot. 3 Different Locations.

I think this is what you are looking for:
You have already made the pivot, you just need to aggregate the result of the pivot table accordingly.
Assumption: Grouping by ItemNmbr,ITEMDESC,EXTDCOST,Loc1,Loc2,HUB,INLAND,Loc,[OLD
Loc],[IN TRANSIT]
SELECT ItemNmbr ,
ITEMDESC ,
QtyOnOrder=SUM(QtyOnOrder) ,
QtyBackordered=SUM(QtyBackordered) ,
TotalInventory=SUM(TotalInventory) ,
EXTDCOST,
InventoryValue = SUM(InventoryValue) ,
Loc1,
Loc2,
HUB,
INLAND,
Loc,
[OLD Loc],
[IN TRANSIT]
FROM ( SELECT DISTINCT ItemNmbr ,
ITEMDESC ,
Location ,
QtyOnhand ,
QtyOnOrder ,
QtyBackordered ,
TotalInventory ,
EXTDCOST ,
InventoryValue
FROM #ssrsFinal
) AS p PIVOT
(SUM(QTYOnHand) FOR Location IN ( Loc1, Loc2, HUB, INLAND, Loc, [OLD Loc],[IN TRANSIT] )
) AS pvt
GROUP BY ItemNmbr ,
ITEMDESC ,
EXTDCOST,
Loc1,
Loc2,
HUB,
INLAND,
Loc,
[OLD Loc],
[IN TRANSIT] ;
In Response to the comment:
Sample data set:
CREATE TABLE #ssrsFinal (ItemNmbr VARCHAR(10),
ITEMDESC VARCHAR(100),
Location VARCHAR(10),
QtyOnhand INT,
QtyOnOrder INT,
QtyBackordered INT,
TotalInventory INT,
EXTDCOST DECIMAL(20,5),
InventoryValue DECIMAL(20,2))
INSERT INTO #ssrsFinal
VALUES
('94185BJGD','SS MESH ROAST PAN, 2X GRILL CLAWS, STAM HNDL, GD','Something',0,0,0,0,14.18000,0),
('94185BJGD','SS MESH ROAST PAN, 2X GRILL CLAWS, STAM HNDL, GD','Something',0,0,0,0,14.18000,0),
('94185BJGD','SS MESH ROAST PAN, 2X GRILL CLAWS, STAM HNDL, GD','Something',3,0,0,3,14.18000,42.54)
In response to the comment "...insert values instead of "something" for location try adding a different location from the examples and then run your query again, it will pull back two rows. I tried INLAND, HUB, and LOC.":
SELECT ItemNmbr ,
ITEMDESC ,
QtyOnOrder=SUM(QtyOnOrder) ,
QtyBackordered=SUM(QtyBackordered) ,
TotalInventory=SUM(TotalInventory) ,
EXTDCOST,
InventoryValue = SUM(InventoryValue) ,
Loc1=SUM(Loc1),
Loc2=SUM(Loc2),
HUB=SUM(HUB),
INLAND=SUM(INLAND),
Loc=SUM(Loc),
[OLD Loc]=SUM([OLD Loc]),
[IN TRANSIT]=SUM([IN TRANSIT])
FROM ( SELECT DISTINCT ItemNmbr ,
ITEMDESC ,
Location ,
QtyOnhand ,
QtyOnOrder ,
QtyBackordered ,
TotalInventory ,
EXTDCOST ,
InventoryValue
FROM #ssrsFinal
) AS p PIVOT
(SUM(QTYOnHand) FOR Location IN ( Loc1, Loc2, HUB, INLAND, Loc, [OLD Loc],[IN TRANSIT] )
) AS pvt
GROUP BY ItemNmbr ,
ITEMDESC ,
EXTDCOST ;
Results:

Related

Summarize values from month to month

I have a table like this.
https://i.stack.imgur.com/XpPZi.png
I need to add up the phase duration for each ID and each phase from month to month. If a phase does not occur in a month, then in this month I need the sum from this phase in the previous month, so that in every month is every phase from the past (+ value from current month if this phase exist in the month).
Expected result
https://i.stack.imgur.com/ukX0I.png
My issue is, that I don't get the sum for each phase in the month an don't get the phase in the month if this phase is not occur in the month.
Can someone please help me?
CREATE TABLE [dbo].[Tab_Status_Test](
[ID] [int] NULL,
[Phase] [nvarchar](50) NULL,
[Phase_duration] [int] NULL,
[EOM_Date] [date] NULL
) ON [PRIMARY]
insert into Tab_status_test
(ID ,Phase,Phase_duration, EOM_Date)
values
('1' ,'C' , '22','2021/02/28')
,('1' ,'A' , '13','2021/03/31')
,('1' ,'A' , '5','2021/03/31')
,('1' ,'B' , '2','2021/03/31')
,('1' ,'B' , '19','2021/04/30')
,('1' ,'A' , '3','2021/04/30')
,('1' ,'B' , '1','2021/04/30')
,('1' ,'A' , '3','2021/04/30')
,('1' ,'B' , '22','2021/05/31')
,('1' ,'C' , '22','2021/06/30')
,('1' ,'D' , '20','2021/07/31')
,('1' ,'A' , '2','2021/07/31')
,('2' ,'C' , '22','2021/02/28')
,('2' ,'A' , '13','2021/03/31')
,('2' ,'A' , '5','2021/03/31')
,('3' ,'B' , '2','2021/03/31')
,('3' ,'B' , '19','2021/04/30')
,('2' ,'A' , '3','2021/04/30')
,('3' ,'B' , '1','2021/04/30')
,('2' ,'A' , '3','2021/04/30')
,('2' ,'B' , '22','2021/05/31')
,('3' ,'C' , '22','2021/06/30')
,('3' ,'D' , '20','2021/07/31')
,('3' ,'A' , '2','2021/07/31')
This is my code
WITH Sum_Dur
AS
(
SELECT ID
,EOM_Date
,phase
,Phase_duration
,LAG(Phase_duration) OVER (Partition BY phase, eom_date ORDER BY phase,eom_date) as PrevEvent
FROM [CM_PT].[dbo].Tab_Status_Test
)
SELECT *,
SUM(PrevEvent+Phase_duration) AS SummedCount
FROM Sum_Dur
GROUP BY ID
,EOM_Date
,phase
,Phase_duration
, PrevEvent
The main thing that you want is a running sum, which you can get using SUM() OVER(PARTITION BY ... ORDER BY ...).
Since you want to include gaps, you will need to generate a complete set of IDs, Dates and Phases, which you can do with several SELECT DISTINCT ... subqueries CROSS JOINed together.
Because you data contains multiple entries with activity for the same ID, date, and phase, that data needs to be grouped to avoid duplicate rows in the results.
The final piece is eliminating early results before any activity has occurred. That can be done by wrapping everything else up as another subselect to apply a WHERE Phase_duration > 0 condition.
The result is something like:
SELECT *
FROM (
-- Running totals
SELECT I.ID, D.EOM_Date, P.Phase,
SUM(T.Phase_duration) OVER(Partition by I.ID, P.Phase ORDER BY D.EOM_DATE) AS Phase_duration
FROM (SELECT DISTINCT ID FROM Tab_status_test) I
CROSS JOIN (SELECT DISTINCT EOM_Date FROM Tab_status_test) D
CROSS JOIN (SELECT DISTINCT Phase FROM Tab_status_test) P
LEFT JOIN (
-- Monthly totals
SELECT ID, EOM_Date, Phase, SUM(Phase_duration) AS Phase_duration
FROM Tab_status_test T
GROUP BY ID, EOM_Date, Phase
) T ON T.ID = I.ID AND T.EOM_Date = D.EOM_Date AND T.Phase = P.Phase
) A
WHERE A.Phase_duration > 0
ORDER BY A.ID, A.EOM_Date, A.Phase
Partial results:
ID
EOM_Date
Phase
Phase_duration
1
2021-02-28
C
22
1
2021-03-31
A
18
1
2021-03-31
B
2
1
2021-03-31
C
22
1
2021-04-30
A
24
1
2021-04-30
B
22
1
2021-04-30
C
22
See this db<>fiddle.
The above assumes that there is at least some activity in every month. If you could potentially have a gap where there is no activity for an entire month, you will need to replace the distinct-date subselect with a calendar gererator.
Your "expected results" were slightly different from the results I got. In particular, the total phase duration for {ID = 1, EOM_Date = 2022-04-30, Phase = B} should be 22 instead of 21 based on your supplied data.
If you want to order your data as C/A/B, you can replace the Phase term in the ORDER BY with a case statement that maps teh values to an alternate sort order. Something like CASE Phase WHEN 'C' THEN 1 WHEN 'A' THEN 2 WHEN 'B' THEN 3 END.

The error message is [Amazon](500310) Invalid operation: This type of correlated subquery pattern is not supported due to internal error

This is the query
CREATE TABLE dw_prestage.check_fact_update
AS
SELECT transaction_id,
transaction_line_id,
subsidiary_id
FROM ( SELECT transaction_id,
transaction_line_id,
subsidiary_id
FROM( SELECT
document_number ,
transaction_number ,
transaction_id ,
transaction_line_id ,
transaction_order ,
custom_form_id ,
document_status ,
transaction_type ,
currency_id ,
trandate ,
exchange_rate ,
account_id ,
amount ,
amount_foreign ,
gross_amount ,
net_amount ,
net_amount_foreign ,
quantity ,
item_id ,
item_unit_price ,
tax_item_id ,
tax_amount ,
location_id ,
class_id ,
subsidiary_id ,
accounting_period_id ,
check_id ,
check_type ,
created_by_id ,
create_date ,
date_last_modified ,
trx_type ,
memo
FROM dw_prestage.check_fact a2
WHERE NOT EXISTS ( SELECT 1 FROM dw_prestage.check_fact_insert b2
WHERE b2.transaction_id = a2.transaction_id
AND b2.transaction_line_id = a2.transaction_line_id
AND a2.subsidiary_id = b2.subsidiary_id
)
MINUS
SELECT
document_number ,
transaction_number ,
transaction_id ,
transaction_line_id ,
transaction_order ,
custom_form_id ,
document_status ,
transaction_type ,
currency_id ,
trandate ,
exchange_rate ,
account_id ,
amount ,
amount_foreign ,
gross_amount ,
net_amount ,
net_amount_foreign ,
quantity ,
item_id ,
item_unit_price ,
tax_item_id ,
tax_amount ,
location_id ,
class_id ,
subsidiary_id ,
accounting_period_id ,
check_id ,
check_type ,
created_by_id ,
create_date ,
date_last_modified ,
trx_type ,
memo
FROM dw_stage.check_fact a1
WHERE EXISTS ( SELECT 1 FROM dw_prestage.check_fact b1
WHERE b1.transaction_id = a1.transaction_id
AND b1.transaction_line_id = a1.transaction_line_id
AND a1.subsidiary_id = b1.subsidiary_id
)
)
) a
WHERE NOT EXISTS (SELECT 1
FROM dw_prestage.check_fact_insert aa
WHERE aa.transaction_id = a.transaction_id
AND aa.transaction_line_id = a.transaction_line_id);
plz suggest any alternative way to replace this query.
The error is because the queries in your NOT EXISTS clauses reference a table outside of the of the clause. Convert the NOT EXISTS clause into a LEFT JOIN with a predicate to exclude any matches. This pattern is often called an "anti-join".
Current:
FROM (…) a
WHERE NOT EXISTS (SELECT 1
FROM dw_prestage.check_fact_insert aa
WHERE aa.transaction_id = a.transaction_id
AND aa.transaction_line_id = a.transaction_line_id)
Rewrite:
FROM (…) a
LEFT JOIN dw_prestage.check_fact_insert aa
ON a.transaction_id = aa.transaction_id
AND a.transaction_line_id = aa.transaction_line_id
WHERE aa.transaction_id IS NULL

SUM OVER PARTITION to calculate running total

I am trying to modify my query to include a running total for each county in my report. Below is my working query with an attempt to use SUM OVER PARTITION commented out:
SELECT DATEPART(MONTH, r.received_date) AS [MonthID] ,
DATENAME(MONTH, r.received_date) AS [Month] ,
o.name AS [CountyName] ,
rsc.description AS [Filing] ,
COUNT(r.id) AS [Request_Total] ,
CAST (AVG(CAST (DATEDIFF(HOUR, received_date, completion_date) AS DECIMAL(8,2))) / 24 AS DECIMAL(8,2)) AS [Total_Time_Days]
--SUM(r.id) OVER (PARTITION BY o.name) AS [TotalFilings]
FROM dbo.requests AS [r]
INNER JOIN dbo.organizations AS [o] ON o.id = r.submitted_to_organiztion_id
INNER JOIN dbo.request_status_codes AS [rsc] ON rsc.code = r.request_status_code
WHERE r.submitted_to_organiztion_id < 68
AND r.request_type_code = 1
AND CAST(r.received_date AS DATE) >= '01/01/2016'
AND CAST(r.received_date AS DATE) <= '06/30/2016'
AND o.name = 'Alachua'
GROUP BY DATENAME(MONTH, r.received_date) ,
DATEPART(MONTH, r.received_date) ,
o.name ,
rsc.description
ORDER BY DATEPART(MONTH, r.received_date) ,
CountyName ,
Filing;
And the results look correct:
Perhaps I am misusing the SUM PARTITION BYbut my end goal is to add an additional column that will sum the filing types for each county by month.
For example, the additional column for the month of January should be 13,654 while February should be 14,238 and so on.
Could I get some advice on how to get this query working correctly? Thanks,
Not sure this is the best way or more efficient, but I was able to create a sub-query to obtain the results I wanted. I do believe a CTE or use of a Windows function would be better, but I haven't been able to get it to work. Here is my query however:
SELECT X.[MonthID] ,
X.[Month] ,
X.[CountyName] ,
X.[Filing] ,
X.[Avg_Time_Days] ,
SUM(X.Request_Total) AS [Total_Requests]
FROM ( SELECT DATEPART(MONTH, r.received_date) AS [MonthID] ,
DATENAME(MONTH, r.received_date) AS [Month] ,
o.name AS [CountyName] ,
rsc.description AS [Filing] ,
COUNT(r.id) AS [Request_Total] ,
CAST (AVG(CAST (DATEDIFF(HOUR, received_date,
completion_date) AS DECIMAL(8, 2)))
/ 24 AS DECIMAL(8, 2)) AS [Avg_Time_Days]
--, SUM(r.id) OVER (PARTITION BY o.name, rsc.description) AS [TotalFilings]
FROM dbo.requests AS [r]
INNER JOIN dbo.organizations AS [o] ON o.id = r.submitted_to_organiztion_id
INNER JOIN dbo.request_status_codes AS [rsc] ON rsc.code = r.request_status_code
WHERE r.submitted_to_organiztion_id < 68
AND r.request_type_code = 1
AND CAST(r.received_date AS DATE) >= '01/01/2016'
AND CAST(r.received_date AS DATE) <= '06/30/2016'
--AND o.name = 'Alachua'
GROUP BY DATENAME(MONTH, r.received_date) ,
DATEPART(MONTH, r.received_date) ,
o.name ,
rsc.description
--, r.id
--ORDER BY DATEPART(MONTH, r.received_date) ,
-- CountyName ,
-- Filing
) AS X
GROUP BY X.[MonthID] ,
X.[Month] ,
X.[CountyName] ,
X.[Filing] ,
X.[Avg_Time_Days]
ORDER BY X.[MonthID] ,
X.[Month] ,
X.[CountyName] ,
X.[Filing];

How to order UNPIVOT

I have the following UNPIVOT code and I would like to order it by the FactSheetSummary columns so that when it is converted to rows it is order 1 - 12:
INSERT INTO #Results
SELECT DISTINCT ReportingDate, PortfolioID,ISIN, PortfolioNme, Section,REPLACE(REPLACE(Risks,'‘',''''),'’','''')
FROM
(SELECT DISTINCT
ReportingDate
, PortfolioID
, ISIN
, PortfolioNme
, Section
, FactSheetSummary_1, FactSheetSummary_2, FactSheetSummary_3
, FactSheetSummary_4, FactSheetSummary_5, FactSheetSummary_6
, FactSheetSummary_7, FactSheetSummary_8, FactSheetSummary_9
, FactSheetSummary_10, FactSheetSummary_11, FactSheetSummary_12
FROM #WorkingTableFactsheet) p
UNPIVOT
(Risks FOR FactsheetSummary IN
( FactSheetSummary_1, FactSheetSummary_2, FactSheetSummary_3
, FactSheetSummary_4, FactSheetSummary_5, FactSheetSummary_6
, FactSheetSummary_7, FactSheetSummary_8, FactSheetSummary_9
, FactSheetSummary_10, FactSheetSummary_11, FactSheetSummary_12)
)AS unpvt;
--DELETE records where there are no Risk Narratives
DELETE FROM #Results
WHERE Risks = ''
SELECT
ReportingDate
, PortfolioID
, ISIN
, PortfolioNme
, Section
, Risks
, ROW_NUMBER() OVER(PARTITION BY ISIN,Section ORDER BY ISIN,Section,Risks) as SortOrder
FROM #Results
order by ISIN, Risks
Is it possible to do this? I thought the IN of the UNPIVOT would dictate the order? Do I need to add a column to dictate which I would like to be 1 through to 12?
Just use case expression to order:
order by case FactsheetSummary
when 'FactSheetSummary_1' then 1
when 'FactSheetSummary_2' then 2
when 'FactSheetSummary_12' then 12 end

how to make insert into in select

i want to use insert into in select like this :
INSERT INTO action_periodique (action_periodique_valeur_id, affaire_id , typetache_id , etattache_id , actionemail_id)
SELECT (
INSERT INTO action_periodique_valeur (nom , debut_rappel , fin_rappel , freq_rappel , champ_id , affaire_id)
SELECT nom , debut_rappel , fin_rappel , freq_rappel , champ_id , 430
FROM action_periodique_valeur
WHERE action_periodique.action_periodique_valeur_id = action_periodique_valeur.id
RETURNING id ),
430 , typetache_id , etattache_id ,
(INSERT INTO actionemail ( copiecarbone , destinataires , expediteur , message , repondrea , sujet)
SELECT copiecarbone , destinataires , expediteur , message , repondrea , sujet
FROM actionemail
WHERE action_periodique.actionemail_id = actionemail.id )
FROM action_periodique
where affaire_id = 170
it is possible ?
You provided next to none information about what you are trying to do.
But it seems to me that you are looking for a data modifying CTE.
Something like this:
with c1 as (
INSERT INTO action_periodique_valeur (nom , debut_rappel , fin_rappel , freq_rappel , champ_id , affaire_id)
SELECT nom , debut_rappel , fin_rappel , freq_rappel , champ_id , 430
FROM action_periodique_valeur
WHERE action_periodique.action_periodique_valeur_id = action_periodique_valeur.id
RETURNING id
, c2 as (
INSERT INTO actionemail ( copiecarbone , destinataires , expediteur , message , repondrea , sujet)
SELECT copiecarbone , destinataires , expediteur , message , repondrea , sujet
FROM actionemail
WHERE action_periodique.actionemail_id = actionemail.id
returning id
)
INSERT INTO action_periodique (action_periodique_valeur_id, affaire_id , typetache_id , etattache_id , actionemail_id)
SELECT (select id from c1),
430,
typetache_id,
etattache_id ,
(select id from c2)
FROM action_periodique
where affaire_id = 170;
If this is not what you want you need to be way more specific.