SQL Server unpivot with multiple columns - sql

Trying to get an Unpivot to apply across a few columns and am struggling to get it to work correctly. Maybe its not the right solution so definitely open to suggestions. Here's an example of my dataset
Sample Data Set In Excel
Sample Wanted Data Set In Excel
Sorry for the links, can't quite stick pics in these posts just yet.
Here's the code that I'm close to, it seems like I'm close...but maybe not.
SELECT
RunDate,
ShipMode,
Amt
FROM
(SELECT
CAST(sh.RunDt as DATE) as RunDt,
sh.method1, sh.method2, sh.method3,
sh.method4, sh.method5
FROM
[dbo].sampletable sh
WHERE
RunDt = '2016-10-17') AS P
UNPIVOT (
RunDate FOR ShipMode IN(method1, method2, method3,method4, method5)
) AS Unpvt

You just have a couple of names wrong. You can unpivot using the SQL:
SELECT
RunDt ,ShipMode ,Amt FROM (
SELECT
CAST(sh.RunDt as DATE) as RunDt
,sh.method1
,sh.method2
,sh.method3
,sh.method4
,sh.method5
FROM [dbo].sampletable sh
WHERE RunDt = '2018-10-17'
) AS P UNPIVOT ( Amt FOR ShipMode IN(method1, method2, method3,method4, method5) ) as Unpvt

Rather than UNPIVOT, another option is using a CROSS APPLY. It offers a bit more flexibility
Example
Select A.RunDt
,B.*
From YourTable A
Cross Apply ( values ('Method1',Method1)
,('Method2',Method2)
,('Method3',Method3)
,('Method4',Method4)
,('Method5',Method5)
) B(Overall,Amt)
Where RunDt = '2016-10-17'

Related

How can I query SQL Server table of events and dates into a column with the event as an attribute and the dates in different columns?

I work with a database that has a set list of stored procedures that I am allowed to run. I have been running them with OPENROWSET and placing the stored procedure into a temp table then querying the temp to get the dataset I need to return. Most of the stored procedures return very wide tables of dates that kind of look like this:
ORDER_NUMBER|STEP1_STATUS|STEP1_START|STEP1_END |STEP2_STATUS|STEP2_START|STEP2_END |STEPN_STATUS...
12345 |COMPLETE |01/01/2020 |02/01/2020 |INPROCESS |01/15/2020 |02/01/2020|...
I would like to get a table returned that looks like this:
ORDER_NUMBER|STEP_NUMBER|STEP_STATUS|STEP_START|STEP_END |DURATION_IN_DAYS`
12345 |STEP1 |COMPLETE |01/01/2020 |02/01/2020|31
12345 |STEP2 |INPROCESS |01/15/2020 |02/01/2020|17
What is the best way to do this? Alternatively, what is the best way to structure a table that has close to 100 different start and end dates. The end application for these dates are typically for business professionals working in Excel and Power Query. Thanks!
Just for fun, here is another option that will "dynamically" pivot your your data without actually using dynamic SQL
Example
Select [ORDER_NUMBER]
,[STEP_NUMBER] = concat('STEP',ColGrp+1)
,[STEP_STATUS] = [Status]
,[STEP_START] = try_convert(date,[Start])
,[STEP_END] = try_convert(date,[End])
,DURATION_IN_DAYS = DateDiff(DAY,try_convert(date,[Start]),try_convert(date,[End]))
From (
Select A.ORDER_NUMBER
,ColGrp = (row_number() over(order by (select null))-1)/3
,ColName = substring(item,charindex('_',item+'_')+1,50)
,ColValue = C.Value
From YourTable A
Cross Apply ( values (convert(xml,(Select A.* for XML Raw)))) B(XMLData)
Cross Apply (
Select Item = xAttr.value('local-name(.)', 'varchar(100)')
,Value = xAttr.value('.','varchar(max)')
From B.XMLData.nodes('//#*') xNode(xAttr)
Where xAttr.value('local-name(.)', 'varchar(100)') not in ('ORDER_NUMBER')
) C
) src
Pivot (max(ColValue) for ColName in ([Status],[Start],[End]) ) pvt
Order By ORDER_NUMBER,ColGrp
You can use a CROSS APPLY You'll just have to expanded to the maximum number of STEPS in your table.
Example
Select A.ORDER_NUMBER
,B.*
,DURATION_IN_DAYS = DateDiff(DAY,B.STEP_START,B.STEP_END)
From YourTable A
Cross Apply ( values ('STEP1',[STEP1_STATUS],[STEP1_START],[STEP1_END])
,('STEP2',[STEP2_STATUS],[STEP2_START],[STEP2_END])
) B (STEP_NUMBER,STEP_STATUS,STEP_START,STEP_END)
Returns
ORDER_NUMBER STEP_NUMBER STEP_STATUS STEP_START STEP_END DURATION
12345 STEP1 COMPLETE 2020-01-01 2020-02-01 31
12345 STEP2 INPROCESS 2020-01-15 2020-02-01 17

How to retrieve single column separated by comma with multiples values, and apply join in sql

I have the following two tables in sql.I want to get the calendarId from calenderschedule and join with calendar table to get the calendarcode for each productId. Output format is described below.
MS SQL Server 2012 version string_split is not working. Please help to get the desired output.
Table1: calenderschedule
productid, calendarid
100 1,2,3
200 1,2
Table2: calendar
calendarid, calendarCode
1 SIB
2 SIN
3 SIS
Output:
productId, calendarCode
100 SIB,SIN,SIS
200 SIB,SIN
You can normalize the data by converting to XML and then using CROSS APPLY to split it. Once it's normalized, use the STUFF function to combine the calendar codes into a comma-separated list. Try this:
;WITH normalized_data as (
SELECT to_xml.productid
,split.split_calendarid
FROM
(
SELECT *,
cast('<X>'+replace(cs.calendarid,',','</X><X>')+'</X>' as XML) as xmlfilter
FROM calendarschedule cs
) to_xml
CROSS APPLY
(
SELECT new.D.value('.','varchar(50)') as split_calendarid
FROM to_xml.xmlfilter.nodes('X') as new(D)
) split
) select distinct
n.productid
,STUFF(
(SELECT distinct ', ' + c.calendarCode
FROM calendar c
JOIN normalized_data n2 on n2.split_calendarid = c.calendarid
WHERE n2.productid = n.productid
FOR XML PATH ('')), 1, 1, '') calendarCode
from normalized_data n
I feel like this solution is a bit overly complex, but it's the only way I got it to work. If anybody knows how to simplify it, I'd love to hear some feedback.

Transposing Column Data into Row Data SQL

I have some data that looks like this in an SQL table.
[ID],[SettleDate],[Curr1],[Curr2][Quantity1],[Quantity2],[CashAmount1],[CashAmount2]
The issue i have, i need to create 2 records from this data (all information from 1 and all information of 2). Example below.
[ID],[SettleDate],[Curr1],[Quantity1],[CashAmount1]
[ID],[SettleDate],[Curr2],[Quantity2],[CashAmount2]
Does anyone have an ideas how to do so?
Thanks
A standard (ie cross-RDBMS) solution for this is to use union:
select ID, SettleDate, Curr1, Quantity1, CashAmount1 from mytable
union all select ID, SettleDate, Curr2, Quantity2, CashAmount2 from mytable
Depending on your RBDMS, neater solutions might be available.
Just another option. The ItemNbr 1/2 is just to maintain which element.
Select A.[ID]
,A.[SettleDate]
,B.*
From YourTable A
Cross Apply ( values (1,[Curr1],[Quantity1],[CashAmount1])
,(2,[Curr2],[Quantity2],[CashAmount2])
) B{ItemNbr,Curr,Quantity,CashAmount)

Pivoting 2 column in SQL server

I got result data from table B2BSALES like this
What i can do just with unpivot just like this from this query
SELECT [Date], [Desc], AREA,Value as TotalAmt
FROM [dbo].[StagingSalesB2BINDOMA]
UNPIVOT
(Value FOR AREA in
(TOTAL, Bandung, CIREBON, BANJARMASIN, BATAM, BALI)
)AS unpvt;
just get column city as area
what i want is like this
how can i do it with query , can i use join before pivoting , thanks before
You seem to want to unpivot. I recommend apply :
select t.date, t.[desc], v.area.v.amt
from t cross apply
(values ('Total', total),
('Bandung', bandung),
('Cirebon', cirebon),
. . .
) as v(area, amt);

Multi row to a row sql

I have a table as bellow:
I want query to print output as bellow:
Note: Please, do not downvote. I know the rules of posting answers, but for such of questions there's no chance to post short answer. I posted it only to provide help for those who want to find out how to achieve that, but does not expect ready-to-use solution.
I'd suggest to read these articles:
PIVOT on two or more fields in SQL Server
Pivoting on multiple columns - SQL Server
Pivot two or more columns in SQL Server 2005
At first UNPIVOT then PIVOT. If number of rows for each Pod_ID is not always equal 3 then you need to use dynamic SQL. The basic sample:
SELECT *
FROM (
SELECT Pod_ID,
Purs + CASE WHEN RN-1 = 0 THEN '' ELSE CAST(RN-1 as nvarchar(10)) END as Purs,
[Values]
FROM (
SELECT Pod_ID,
Pur_Qty, --All columns that will be UNPIVOTed must be same datatype
Pur_Price,
CAST(ETD_Date as int) ETD_Date, -- that is why I cast date to int
ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as RN
FROM YourTable
) as p1
UNPIVOT (
[Values] FOR [Purs] IN(Pur_Qty, Pur_Price, ETD_Date)
) as unpvt
) as p2
PIVOT (
MAX([Values]) FOR Purs IN (Pur_Qty,Pur_Price,ETD_Date,Pur_Qty1,Pur_Price1,ETD_Date1,Pur_Qty2,Pur_Price2,ETD_Date2)
) as pvt
Will bring you:
Pod_ID Pur_Qty Pur_Price ETD_Date Pur_Qty1 Pur_Price1 ETD_Date1 Pur_Qty2 Pur_Price2 ETD_Date2
F8E2F614-75BC-4E46-B7F8-18C7FC4E5397 24 22 20160820 400 33 20160905 50 44 20160830