I have below query written by someone(Database is Microsoft SQL server 2017). I do not have access to database to create indexes etc., So only way I can do is optimize below query as efficient as possible.
My query here is,
Can I use Case and WHEN in inner query as used in the below query? Also am currently trying to remove nested queries by using inner join.
Any other ideas will be appreciated for the below queries. I am not asking to give final optimized query, but asking suggestion specific to below query.
WITH ChildPremiumCTE (COVER_PREMIUM_SET_ID,POLICY_ID, ADDRESS_ID, STATUS_CODE,COVER_PREMIUM_MODEL_ID, SUB_PRODUCT_REF
, COVER_PREMIUM_MODEL_REF, DESCRIPTION, PREMIUM_LEVEL_CODE
, PREMIUM_PAYABLE, PREMIUM_DUE, COMMISSION_GST, COMMISSION, COMMISSION_TOTAL,TERRORISM_GST
, TERRORISM_RI, STAMP_DUTY, GST, FSL
, MODIFIED_PREMIUM, TECHNICAL_PREMIUM, BASE_PREMIUM
, PREMIUM_PAYABLE_TERM, PREMIUM_DUE_TERM, COMMISSION_GST_TERM
, COMMISSION_TERM, COMMISSION_TOTAL_TERM, TERRORISM_GST_TERM
, TERRORISM_RI_TERM, STAMP_DUTY_TERM, GST_TERM, FSL_TERM
, MODIFIED_PREMIUM_TERM, TECHNICAL_PREMIUM_TERM, BASE_PREMIUM_TERM
, PREMIUM_PAYABLE_ANNUALISED, PREMIUM_DUE_ANNUALISED, COMMISSION_GST_ANNUALISED
, COMMISSION_ANNUALISED, COMMISSION_TOTAL_ANNUALISED, TERRORISM_GST_ANNUALISED
, TERRORISM_RI_ANNUALISED, STAMP_DUTY_ANNUALISED, GST_ANNUALISED
, FSL_ANNUALISED, MODIFIED_PREMIUM_ANNUALISED, TECHNICAL_PREMIUM_ANNUALISED
, BASE_PREMIUM_ANNUALISED)
AS (SELECT CPP.COVER_PREMIUM_SET_ID
, CPS.POLICY_ID
, CASE WHEN CPS.PREMIUM_LEVEL_CODE = 'PREMITEM' THEN SS.ADDRESS_ID ELSE AD.ADDRESS_ID END ADDRESS_ID
, SS.STATUS_CODE
, COALESCE(CPM.COVER_PREMIUM_MODEL_ID, 0) COVER_PREMIUM_MODEL_ID
, CASE WHEN CPS.PREMIUM_LEVEL_CODE = 'POLSUM' THEN 'POLICY_SUMMARY'
ELSE CASE WHEN CPS.PREMIUM_LEVEL_CODE = 'SITSUM' THEN 'SITUATION_SUMMARY' ELSE CPS.SUB_PRODUCT_REF END END SUB_PRODUCT_REF
, CPS.COVER_PREMIUM_MODEL_REF
, CPS.DESCRIPTION
, CPS.PREMIUM_LEVEL_CODE
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_PAYABLE' THEN CPP.TRANSACTION_AMOUNT END) PREMIUM_PAYABLE
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_DUE' THEN CPP.TRANSACTION_AMOUNT END) PREMIUM_DUE
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_GST' THEN CPP.TRANSACTION_AMOUNT END) COMMISSION_GST
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION' THEN CPP.TRANSACTION_AMOUNT END) COMMISSION
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_TOTAL' THEN CPP.TRANSACTION_AMOUNT END) COMMISSION_TOTAL
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_GST' THEN CPP.TRANSACTION_AMOUNT END) TERRORISM_GST
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_RI' THEN CPP.TRANSACTION_AMOUNT END) TERRORISM_RI
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'STAMP_DUTY' THEN CPP.TRANSACTION_AMOUNT END) STAMP_DUTY
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'GST' THEN CPP.TRANSACTION_AMOUNT END) GST
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'FSL' THEN CPP.TRANSACTION_AMOUNT END) FSL
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'MODIFIED_PREMIUM' THEN CPP.TRANSACTION_AMOUNT END) MODIFIED_PREMIUM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TECHNICAL_PREMIUM' THEN CPP.TRANSACTION_AMOUNT END) TECHNICAL_PREMIUM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'BASE_PREMIUM' THEN CPP.TRANSACTION_AMOUNT END) BASE_PREMIUM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_PAYABLE' THEN CPP.TERM_AMOUNT END) PREMIUM_PAYABLE_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_DUE' THEN CPP.TERM_AMOUNT END) PREMIUM_DUE_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_GST' THEN CPP.TERM_AMOUNT END) COMMISSION_GST_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION' THEN CPP.TERM_AMOUNT END) COMMISSION_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_TOTAL' THEN CPP.TERM_AMOUNT END) COMMISSION_TOTAL_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_GST' THEN CPP.TERM_AMOUNT END) TERRORISM_GST_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_RI' THEN CPP.TERM_AMOUNT END) TERRORISM_RI_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'STAMP_DUTY' THEN CPP.TERM_AMOUNT END) STAMP_DUTY_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'GST' THEN CPP.TERM_AMOUNT END) GST_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'FSL' THEN CPP.TERM_AMOUNT END) FSL_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'MODIFIED_PREMIUM' THEN CPP.TERM_AMOUNT END) MODIFIED_PREMIUM_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TECHNICAL_PREMIUM' THEN CPP.TERM_AMOUNT END) TECHNICAL_PREMIUM_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'BASE_PREMIUM' THEN CPP.TERM_AMOUNT END) BASE_PREMIUM_TERM
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_PAYABLE' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) PREMIUM_PAYABLE_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'PREMIUM_DUE' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) PREMIUM_DUE_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_GST' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) COMMISSION_GST_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) COMMISSION_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'COMMISSION_TOTAL' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) COMMISSION_TOTAL_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_GST' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) TERRORISM_GST_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TERRORISM_RI' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) TERRORISM_RI_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'STAMP_DUTY' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) STAMP_DUTY_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'GST' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) GST_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'FSL' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) FSL_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'MODIFIED_PREMIUM' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) MODIFIED_PREMIUM_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'TECHNICAL_PREMIUM' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) TECHNICAL_PREMIUM_ANNUALISED
, MAX(CASE WHEN CPP.PREMIUM_MODEL_PART_REF = 'BASE_PREMIUM' THEN CPP.FUTURE_ANNUALISED_AMOUNT END) BASE_PREMIUM_ANNUALISED
FROM COVER_PREMIUM_SET As CPS
LEFT JOIN SITUATION_SECTION As SS ON CPS.POLICY_ID = SS.POLICY_ID
AND CPS.SITUATION_SECTION_REF = SS.SITUATION_SECTION_REF
LEFT JOIN COVER_PREMIUM_PART As CPP ON CPS.COVER_PREMIUM_SET_ID = CPP.COVER_PREMIUM_SET_ID
LEFT JOIN ADDRESS As AD ON CPS.POLICY_ID = AD.POLICY_ID
AND AD.ADDRESS_REF = CPS.ENTITY_INSTANCE_REF
AND CPS.PREMIUM_LEVEL_CODE IN ('SITSUM', 'SUBPRODSUM')
LEFT JOIN COVER_PREMIUM_MODEL As CPM ON CPS.COVER_PREMIUM_MODEL_REF = CPM.COVER_PREMIUM_MODEL_REF
GROUP BY CPP.COVER_PREMIUM_SET_ID,
CPS.POLICY_ID,
CPS.DESCRIPTION,
CPS.PREMIUM_LEVEL_CODE,
CPS.COVER_PREMIUM_MODEL_REF,
CPS.SUB_PRODUCT_REF,
CPM.COVER_PREMIUM_MODEL_ID,
SS.SITUATION_SECTION_ID,
SS.ADDRESS_ID,
SS.STATUS_CODE,
CPS.ENTITY_INSTANCE_REF,
AD.ADDRESS_ID )
select * from (SELECT
0 AS COVER_PREMIUM_SET_ID
, a1.POLICY_ID
, a1.ADDRESS_ID
, a1.STATUS_CODE
, CPM_CHILD.PARENT_ID AS COVER_PREMIUM_MODEL_ID
, CASE WHEN CPM.PREMIUM_LEVEL_CODE = 'POLSUM' THEN 'POLICY_SUMMARY'
ELSE CASE WHEN CPM.PREMIUM_LEVEL_CODE = 'SITSUM' THEN 'SITUATION_SUMMARY' ELSE a1.SUB_PRODUCT_REF END END SUB_PRODUCT_REF
, CPM.COVER_PREMIUM_MODEL_REF
, CPM.NAME AS Description
, CPM.PREMIUM_LEVEL_CODE AS PREMIUM_LEVEL_CODE
, sum(a1.PREMIUM_PAYABLE) PREMIUM_PAYABLE
, sum(a1.PREMIUM_DUE) PREMIUM_DUE
, sum(a1.COMMISSION_GST) COMMISSION_GST
, sum(a1.COMMISSION) COMMISSION
, sum(a1.COMMISSION_TOTAL) COMMISSION_TOTAL,sum(a1.TERRORISM_GST) TERRORISM_GST
, sum(a1.TERRORISM_RI) TERRORISM_RI, sum(a1.STAMP_DUTY) STAMP_DUTY,sum(a1.GST ) GST, sum(a1.FSL ) FSL
, sum(a1.MODIFIED_PREMIUM ) MODIFIED_PREMIUM, sum(a1.TECHNICAL_PREMIUM ) TECHNICAL_PREMIUM, sum(a1.BASE_PREMIUM ) BASE_PREMIUM
, sum(a1.PREMIUM_PAYABLE_TERM) PREMIUM_PAYABLE_TERM, sum(a1.PREMIUM_DUE_TERM ) PREMIUM_DUE_TERM
, sum(a1.COMMISSION_GST_TERM ) COMMISSION_GST_TERM, sum(a1.COMMISSION_TERM ) COMMISSION_TERM
, sum(a1.COMMISSION_TOTAL_TERM ) COMMISSION_TOTAL_TERM, sum(a1.TERRORISM_GST_TERM ) TERRORISM_GST_TERM
, sum(a1.TERRORISM_RI_TERM ) TERRORISM_RI_TERM, sum(a1.STAMP_DUTY_TERM ) STAMP_DUTY_TERM
, sum(a1.GST_TERM ) GST_TERM, sum(a1.FSL_TERM ) FSL_TERM, sum(a1.MODIFIED_PREMIUM_TERM ) MODIFIED_PREMIUM_TERM
, sum(a1.TECHNICAL_PREMIUM_TERM ) TECHNICAL_PREMIUM_TERM, sum(a1.BASE_PREMIUM_TERM ) BASE_PREMIUM_TERM
, sum(a1.PREMIUM_PAYABLE_ANNUALISED) PREMIUM_PAYABLE_ANNUALISED, sum(a1.PREMIUM_DUE_ANNUALISED ) PREMIUM_DUE_ANNUALISED
, sum(a1.COMMISSION_GST_ANNUALISED ) COMMISSION_GST_ANNUALISED, sum(a1. COMMISSION_ANNUALISED ) COMMISSION_ANNUALISED
, sum(a1. COMMISSION_TOTAL_ANNUALISED ) COMMISSION_TOTAL_ANNUALISED, sum(a1.TERRORISM_GST_ANNUALISED ) TERRORISM_GST_ANNUALISED
, sum(a1.TERRORISM_RI_ANNUALISED ) TERRORISM_RI_ANNUALISED, sum(a1.STAMP_DUTY_ANNUALISED ) STAMP_DUTY_ANNUALISED
, sum(a1.GST_ANNUALISED ) GST_ANNUALISED, sum(a1.FSL_ANNUALISED ) FSL_ANNUALISED
, sum(a1.MODIFIED_PREMIUM_ANNUALISED ) MODIFIED_PREMIUM_ANNUALISED
, sum(a1.TECHNICAL_PREMIUM_ANNUALISED ) TECHNICAL_PREMIUM_ANNUALISED
, sum(a1.BASE_PREMIUM_ANNUALISED) BASE_PREMIUM_ANNUALISED
FROM COVER_PREMIUM_MODEL CPM,
COVER_PREMIUM_MODEL CPM_CHILD,
ChildPremiumCTE a1
WHERE
CPM.PREMIUM_LEVEL_CODE = 'PREMRLUP'
AND CPM_CHILD.PARENT_ID = CPM.COVER_PREMIUM_MODEL_ID
AND CPM_CHILD.COVER_PREMIUM_MODEL_REF = a1.COVER_PREMIUM_MODEL_REF
GROUP BY
a1.POLICY_ID,
a1.ADDRESS_ID,
CPM_CHILD.PARENT_ID,
CPM.NAME,
CPM.PREMIUM_LEVEL_CODE,
a1.SUB_PRODUCT_REF,
CPM.COVER_PREMIUM_MODEL_REF,
a1.STATUS_CODE
UNION ALL
select * from ChildPremiumCTE) CoverPremium where CoverPremium.POLICY_ID = 77780029
So far what I have improved is,
Made union to union all
Trying to convert subqueries into where clause
built in functions like MAX, SUM to like string literal
First suggestion is same as #LukStorms.Also always use alias of table and prefix them in column so that it is very easy to understand and debug.
Can I use Case and WHEN in inner query as used in the below query?
Everything has cost.It seem that in this case cost is negligible.
Any other ideas will be appreciated for the below queries. I am not
asking to give final optimized query, but asking suggestion specific
to below query.
GROUP BY on All column is always bad idea.First Using CTE or #Temp table
write Group By query using only require table and Group By on Key column only.
Suppose you need some other column also which is not part of aggregate or Group By,then no problem don't try to use that column here.
Join the same table in main query to get those columns which is not part of aggregate.
Then in Main query again join that CTE or temp table with other table.
This is how you should design your query .
PREMIUM_MODEL_PART_REF and TRANSACTION_AMOUNT belong to which table ?
Table COVER_PREMIUM_MODEL are use 3 times in query.Put the require data of COVER_PREMIUM_MODEL on #temp table .There must be some common result in all three join.
Excerpt
select * from (Select * blah blah
UNION ALL
select * from ChildPremiumCTE) a2 where a2.POLICY_ID = 77780029
WHY use where POLICY_ID = 77780029 in the end ?
This way first so many rows will be process in inner query then finally reduce to POLICY_ID = 77780029.
So WHY not use POLICY_ID = 77780029 in inner query somewhere in the first place.
built in functions like MAX, SUM to like string literal
It depend what type of UDF it is and what you have written in it.
In short UDF are notoriously Bad Perform-ant most of the time.
It do not appear to be that MAX, SUM need UDF.
On SQL Server 2014 I use the following code:
CREATE TABLE TempTable
(
LType varchar(255),
LStatus varchar(255),
PAmount decimal(16,2),
RAmount decimal(16,2));
INSERT INTO TempTable (LType, LStatus, PAmount, RAmount)
VALUES ('TypeA','StatusA', '1000', '10'),
('TypeB', 'StatusC', '500', '50'),
('TypeC', 'StatusB', '2500', '100'),
('TypeB', 'StatusB', '1000', '50'),
('TypeA', 'StatusA', '3000', '25'),
('TypeC', 'StatusB', '2200', '50');
Select Ltype, Lstatus, SUM(PAmount) as PAmount, SUM(RAmount) as RAmount
From TempTable
Where PAmount > 0
Group By LType, LStatus
to get this table:
What I’m trying to achieve is:
I used pivot but was unable to apply it simultaneously for PAmount and RAmount under Status columns.
Can anyone help with solution?
You can use conditional aggregation for this. This assumes you will always have these values. If you need this to be dynamic then there is a bit more work to do.
select StatusA_PAMount = max(case when Totals.Lstatus = 'StatusA' then Totals.PAmount end)
, StatusA_RAMount = max(case when Totals.Lstatus = 'StatusA' then Totals.RAmount end)
, StatusB_PAMount = max(case when Totals.Lstatus = 'StatusB' then Totals.PAmount end)
, StatusB_RAMount = max(case when Totals.Lstatus = 'StatusB' then Totals.RAmount end)
, StatusC_PAMount = max(case when Totals.Lstatus = 'StatusC' then Totals.PAmount end)
, StatusC_RAMount = max(case when Totals.Lstatus = 'StatusC' then Totals.RAmount end)
from
(
Select Lstatus
, SUM(PAmount) as PAmount
, SUM(RAmount) as RAmount
From TempTable
Where PAmount > 0
Group By LStatus
) Totals
I have a SQL result set that looks like the following:
How can I get this result to display only ONE row for each ItemCode? Using a GROUP BY does not seem to work as it requires me to include columns that prevent the grouping I'm looking for.
The query I have written is pulling data from a table with a row for each warehouse and I am trying to format it in a way that I only have one row for each ItemCode. I think pivoting is the term what I'm trying to do..
Here is what my query looks like currently:
SELECT
ItemCode,
ISNULL((SELECT Quantity WHERE WhsCode = 10), 0) 'Whs10QTY',
ISNULL((SELECT Quantity WHERE WhsCode = 20), 0) 'Whs20QTY',
ISNULL((SELECT SalesAmt WHERE WhsCode = 10), 0) 'Whs10SalesAmt',
ISNULL((SELECT SalesAmt WHERE WhsCode = 20), 0) 'Whs20SalesAmt',
ISNULL((SELECT GrssProfit WHERE WhsCode = 10), 0) 'Whs10GrssProfit',
ISNULL((SELECT GrssProfit WHERE WhsCode = 20), 0) 'Whs20GrssProfit'
FROM
#Table t
Note: I may need help rewording and retitling this question as to make it more useful for the community. Thanks for any help guys!
I think you can simplify this as such:
Select ItemCode
,Whs10QTY = sum(case when WhsCode = 10 then Quantity else 0 end)
,Whs20QTY = sum(case when WhsCode = 20 then Quantity else 0 end)
,Whs10SalesAmt = sum(case when WhsCode = 10 then SalesAmt else 0 end)
,Whs20SalesAmt = sum(case when WhsCode = 20 then SalesAmt else 0 end)
,Whs10GrssProfit = sum(case when WhsCode = 10 then GrssProfit else 0 end)
,Whs20GrssProfit = sum(case when WhsCode = 20 then GrssProfit else 0 end)
From #Table t
Group By ItemCode
I know SQL Server Pivot, but this time I think I will need something more complex then a simple pivoted value.
Here it is an SQL fiddle example.
So I have a table where I have maximum 3 rows for one startcity - endcity combination.
In a query I need to get these combinations in just one row, and I need just those combinations, where there are 3 rows.
Please advice,
You can do this as a crosstab like this.
with NumberedValues as
(
SELECT EndCity
, StartDate
, EndDate
, Price
, ROW_NUMBER() OVER(PARTITION BY StartCity, EndCIty ORDER BY StartDate) as RowNum
FROM [dbo].[BestPrice]
)
SELECT EndCity,
max(CASE WHEN RowNum = 1 THEN StartDate END) as StartDate1,
max(CASE WHEN RowNum = 1 THEN Enddate END) as EndDate1,
max(CASE WHEN RowNum = 1 THEN Price END) as Price1,
max(CASE WHEN RowNum = 2 THEN StartDate END) as StartDate2,
max(CASE WHEN RowNum = 2 THEN Enddate END) as EndDate2,
max(CASE WHEN RowNum = 2 THEN Price END) as Price2,
max(CASE WHEN RowNum = 3 THEN StartDate END) as StartDate3,
max(CASE WHEN RowNum = 3 THEN Enddate END) as EndDate3,
max(CASE WHEN RowNum = 3 THEN Price END) as Price3
FROM NumberedValues
group by EndCity
I have the following table:
BoughtItems
UserID ItemID StoreID Quantity Price
1 1 1 1 1
1 4 1 2 3
1 5 2 1 3
Let's assume that it will be no more then five items for each user in BoughtItems table.
I want to have all the clients from some StoreID and all items that were purchased, in this format... for StoreID = 1 the result will be:
UserID Item1ID Item2ID Item3ID Item4ID Item5ID
1 1 4 [empty] [empty] [empty]
DECLARE #StoreID INT;
SET #StoreID = 1;
;WITH x AS
(
SELECT UserID, ItemID,
rn = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY ItemID)
FROM dbo.BoughtItems
WHERE StoreID = #StoreID
)
SELECT UserID,
Item1ID = MAX(CASE WHEN rn = 1 THEN ItemID END),
Item2ID = MAX(CASE WHEN rn = 2 THEN ItemID END),
Item3ID = MAX(CASE WHEN rn = 3 THEN ItemID END),
Item4ID = MAX(CASE WHEN rn = 4 THEN ItemID END),
Item5ID = MAX(CASE WHEN rn = 5 THEN ItemID END)
FROM x WHERE rn <= 5
GROUP BY UserID;