UNPIVOT not getting NULL values - sql

I have the following :
SELECT Custid, Shipperid, Freight
FROM Sales.FreightTotals
UNPIVOT( Freight FOR Shipperid IN([1],[2],[3]) ) AS U;
I have the following result :
custid shipperid freight
1 1 25
1 3 100
2 2 75
My expected output after getting NULL values :
custid shipperid freight
1 1 25
1 2 NULL
1 3 100
2 1 NULL
2 2 75
2 3 NULL

Use a CTE to get NULL as 0.00 for example then replace the 0.00 by NULL using NULLIF() :
WITH C AS
(
SELECT custid,
ISNULL([1], 0.00) AS [1],
ISNULL([2], 0.00) AS [2],
ISNULL([3], 0.00) AS [3]
FROM Sales.FreightTotals
)
SELECT custid, shipperid, NULLIF(freight, 0.00) AS freight
FROM C
UNPIVOT( freight FOR shipperid IN([1],[2],[3]) ) AS U;

That is considered a feature of unpivot. Use apply instead:
SELECT ft.custid, v.shipperid, v.freight
FROM Sales.FreightTotals ft CROSS APPLY
(VALUES (1, ft.[1]), (2, ft.[2]), (3, ft.[3])) AS v(shipperid, freight);

Related

Turn values into column names

I have one table which contains some rows as below :
Sr. Name Product Qty
1 Yogesh ALB 1
2 Suresh AMS 2
3 Yogesh ALB 2
4 Mahesh MAS 5
Now, i want display records as in below style...
Sr. Name ALB AMS MAS
1 Yogesh 3 0 0
2 Suresh 0 2 0
3 Mahesh 5 0 0
BEGIN TRAN
CREATE TABLE #temp
(
Sr Int NOT null, Name Varchar(255), Product Varchar(255) , Qty numeric
)
INSERT INTO #temp
SELECT 1 ,'Yogesh', 'ALB', 1 UNION All
Select 2 , 'Suresh','AMS',2 UNION All
Select 3 , 'Yogesh' , 'ALB',2 UNION All
Select 4 , 'Mahesh','MAS',5
SELECT NAME,ISNULL(ALB,0) AS ALB,ISNULL(AMS,0) AS AMS,ISNULL(MAS,0) AS MAS
FROM (
SELECT
(Name) as Name,left(Product,3)as Product,
Isnull(Qty,0) as Qty
FROM #temp
) as s
PIVOT (SUM(QTY) FOR PRODUCT IN (ALB, AMS, MAS)) AS pvt
ORDER BY Name
ROLLBACK TRAN
Try with the below query.
SELECT ROW_NUMBER()OVER(ORDER BY (SELECT 1)) [Sr.],Name,ISNULL(ALB,0) AS ALB,ISNULL(AMS,0) AS AMS,ISNULL(MAS,0) AS MAS
FROM (
SELECT Name,Product,
ISNULL(Qty,0) as Qty
FROM #temp
) as s
PIVOT (SUM(QTY) FOR PRODUCT IN (ALB, AMS, MAS)) AS pvt
Use
SELECT NAME,ISNULL(ALB,0) AS ALB,ISNULL(AMS,0) AS AMS,ISNULL(MAS,0) AS MAS
FROM
(SELECT NAME,PRODUCT,SUM(QTY) QTY FROM TABLENAME
GROUP BY NAME,PRODUCT) A
PIVOT(SUM(QTY) FOR PRODUCT IN (ALB,AMS,MAS)) AS PVT

SQL Pivot Query for pivot values

iItemKey Qty FreeQty Unit TaxCatKey TaxVal
7 1 1 1 1 4.00
7 1 1 1 1 1.00
I need output as
iItemKey Qty FreeQty Unit TaxCatKey VAT A.VAt
7 1 1 1 1 4.00 1.00
Here is my query. But i get VAT and A.Vat values as Null
WITH T
AS (SELECT T_ItemRequestSub.iItemKey, T_ItemRequestSub.Qty, T_ItemRequestSub.FreeQty, T_ItemRequestSub.Unit, T_ItemRequestSub.TaxType,
M_Mt_TaxCategorySub.iTaxCatKey , M_Mt_TaxCategorySub.iTaxVal
FROM T_ItemRequestSub INNER JOIN
T_ItemRequest ON T_ItemRequestSub.iReqKey = T_ItemRequest.iKey INNER JOIN
M_Mt_TaxCategory ON T_ItemRequestSub.TaxType = M_Mt_TaxCategory.iKey INNER JOIN
M_Mt_TaxCategorySub ON M_Mt_TaxCategory.iKey = M_Mt_TaxCategorySub.iTaxCatKey where T_ItemRequestSub.iKey = 2)
SELECT *
FROM T PIVOT ( sum (iTaxVal) FOR TaxType IN (
[Vat],
[A.Vat]
) ) AS pvt
Please Help
The only distinct value is TaxVal so I suspect you are trying to do following:
WITH Src AS --Your source table
(
SELECT * FROM (VALUES
(7, 1, 1, 1, 1, 4.00),
(7, 1, 1, 1, 1, 1.00)
)T(iItemKey, Qty, FreeQty, Unit, TaxCatKey, TaxVal)
)
SELECT * FROM
(
SELECT iItemKey, Qty, FreeQty, Unit, TaxCatKey, TaxVal, CASE WHEN TaxVal = 1.00 THEN 'VAT' ELSE 'A.VAT' END Col
FROM Src
) T
PIVOT (MAX(TaxVal) FOR Col IN ([VAT], [A.VAT])) P

How to select data rows into columns w/out knowing all values

Below is a table I have with some order details.
OrderID TypeID Amount
11148 1 900
11148 7 30
11148 6 75
12506 3 100
12506 4 60
16845 1 30
Is it possible to return something like this:
OrderID TypeID1 Amount1 TypeID2 Amount2 TypeID3 Amount3
11148 1 900 7 30 6 75
12506 3 100 4 60 null null
16845 1 30 null null null null
I want to get results like this so I can join into another result set with other order information but I can only have one row per ID. I've been trying with a Pivot but it seems I need to know all the possible results for TYPEID and have that many columns instead of just the 3 for TYPEID and 3 for AMOUNT that I'm looking for.
Below is the Pivot table I know how to get to work but this is not desired because then I have columns for each ID type but I would rather have those in the rows too.
SELECT OrderID
,[1] as Amount1
,[2] as Amount2
,[3] as Amount3
,[4] as Amount4
,[5] as Amount5
,[6] as Amount6
,[7] as Amount7
FROM (
SELECT ORDERID, TYPEID, AMOUNT
FROM Order_Details
)x
PIVOT
(
MAX(AMOUNT)
FOR TYPEID in ([1],[2],[3],[4],[5],[6],[7])
)P
OrderID Amount1 Amount2 Amount3 Amount4 Amount5 Amount6 Amount7
11148 900 null null null null 75 30
12506 null null 100 60 null null null
16845 30 null null null null null null
the solution is to make a self outer join combined with row_number over partition like:
select t1.OrderId as OrderID1, t1.TypeID as TypeID1, t1.Amount as Amount1,
t2.TypeID as TypeID2, t2.Amount as Amount2,
t3.TypeID as TypeID3, t3.Amount as Amount3 from
(
SELECT OrderID, TypeID, Amount
FROM (
select OrderID , TypeID, Amount ,ROW_NUMBER() OVER (PARTITION BY OrderID order by OrderID) AS RN
from tt
)Sub
WHERE rn = 1) t1 left join
(
SELECT OrderID, TypeID, Amount
FROM (
select OrderID , TypeID, Amount ,ROW_NUMBER() OVER (PARTITION BY OrderID order by OrderID) AS RN
from tt
)Sub
WHERE rn = 2) t2 on t1.OrderID=t2.OrderID left join
(
SELECT OrderID, TypeID, Amount
FROM (
select OrderID , TypeID, Amount ,ROW_NUMBER() OVER (PARTITION BY OrderID order by OrderID) AS RN
from tt
)Sub
WHERE rn = 3) t3 on t1.OrderID=t3.OrderID;
live example
by using cross apply and Row_number we can achieve same result
declare #Table1 TABLE
(OrderID int, TypeID int, Amount int)
;
INSERT INTO #Table1
(OrderID, TypeID, Amount)
VALUES
(11148, 1, 900),
(11148, 7, 30),
(11148, 6, 75),
(12506, 3, 100),
(12506, 4, 60),
(16845, 1, 30)
;
;with CTE As (
select OrderID,[TypeID1],[TypeID2],[TypeID3] from (
Select OrderID,
val,
COL + CAST(ROW_NUMBER()OVER(PARTITION BY OrderID ORDER BY OrderID) AS VARCHAR(1))RN
FROM #Table1
CROSS APPLY (VALUES ('TypeID',TypeID))CS(Col,val))T
PIVOT (MAX(VAL) FOR RN IN ([TypeID1],[TypeID2],[TypeID3]))P )
,CTE2 AS (select OrderID,[Amount1],[Amount2],[Amount3] from (
Select OrderID,
val,
COL + CAST(ROW_NUMBER()OVER(PARTITION BY OrderID ORDER BY OrderID) AS VARCHAR(1))RN
FROM #Table1
CROSS APPLY (VALUES ('Amount',Amount))CS(Col,val))T
PIVOT (MAX(VAL) FOR RN IN ([Amount1],[Amount2],[Amount3]))P)
select c.OrderID,c.TypeID1,cc.Amount1,c.TypeID2,cc.Amount2,c.TypeID3,cc.Amount3 from CTE C
LEFT JOIN CTE2 CC
ON c.OrderID = cc.OrderID

Remove duplicate rows displayed in pivot

Basically, I have created a pivot query wherein it will display the total_work_hours per each costcode for each employee.
This is my desired output:
employeeno 8322.170 10184.2648 8321.169 10184.2649 <- costcodes
--------------------------------------------------------------------------
080418 10.00 1.50 NULL NULL
080441 6.50 NULL 1.00 3.00
but this is the result of my query:
employeeno 8322.170 10184.2648 8321.169 10184.2649 <- costcodes
--------------------------------------------------------------------------
080418 10.00 NULL NULL NULL
080418 NULL 1.50 NULL NULL
080441 NULL NULL 1.00 NULL
080441 6.50 NULL NULL NULL
080441 NULL NULL NULL 3.00
This is the result of my inner query:
employeeno costcoding hour_per_costcode
--------------------------------------------------
PH080418 8322.170 10.00
PH080418 10184.2648 1.50
PH080441 8321.169 1.00
PH080441 8322.170 6.50
PH080441 10184.2649 3.00
This is my query:
WITH PivotData AS
(SELECT wa.id,wa.sitecode, wa.companycode, wa.startdate, wa.enddate,
wa.description, wa.ratetypeid, wa_details.employeeno,
CAST(wa_details.costcode AS NVARCHAR(MAX)) + '.' +
CAST(wa_details.subcostcode AS NVARCHAR(MAX)) costcoding ,
wa_details.subcostcode, wa_details.hrswork [hour_per_costcode],
view_ttl_hours.ttl_work_hrs
FROM workallocation wa
INNER JOIN workallocation_details wa_details
ON wa.id = wa_details.workallocationid
INNER JOIN
(SELECT SUM(ttl_work_hrs) ttl_work_hrs, employee_id
FROM vwu_SUM_TIMESHEET_DAILY
WHERE TKSDATE BETWEEN '02-09-2012' AND '02-09-2012'
GROUP BY employee_id
) view_ttl_hours
ON wa_details.employeeno=view_ttl_hours.employee_id WHERE wa.id=99
)
SELECT employeeno, [8322.170], [10184.2648], [8321.169], [10184.2649]
FROM PivotData
PIVOT (MAX([hour_per_costcode])
FOR costcoding
IN ([8322.170], [10184.2648], [8321.169], [10184.2649])
) AS PivotResult
ORDER BY employeeno;
My question is how will I be able to unite the value for my multiple rows so that my desire output will be achieve? I also try the cross tab query but the result is also the same.
I need some guidance on how to solve this; can you help?
Remove the columns you don't need from the CTE. Something like this should work for you.
WITH PivotData AS
(SELECT wa_details.employeeno,
CAST(wa_details.costcode AS NVARCHAR(MAX)) + '.' +
CAST(wa_details.subcostcode AS NVARCHAR(MAX)) costcoding ,
wa_details.subcostcode, wa_details.hrswork [hour_per_costcode]
FROM workallocation wa
INNER JOIN workallocation_details wa_details
ON wa.id = wa_details.workallocationid
INNER JOIN
(SELECT SUM(ttl_work_hrs) ttl_work_hrs, employee_id
FROM vwu_SUM_TIMESHEET_DAILY
WHERE TKSDATE BETWEEN '02-09-2012' AND '02-09-2012'
GROUP BY employee_id
) view_ttl_hours
ON wa_details.employeeno=view_ttl_hours.employee_id WHERE wa.id=99
)
SELECT employeeno, [8322.170], [10184.2648], [8321.169], [10184.2649]
FROM PivotData
PIVOT (MAX([hour_per_costcode])
FOR costcoding
IN ([8322.170], [10184.2648], [8321.169], [10184.2649])
) AS PivotResult
ORDER BY employeeno;
Above query with your data:
WITH PivotData AS
(select 'PH080418' as employeeno, 8322.170 as costcoding, 10.00 as hour_per_costcode union all
select 'PH080418', 10184.2648, 1.50 union all
select 'PH080441', 8321.169, 1.00 union all
select 'PH080441', 8322.170, 6.50 union all
select 'PH080441', 10184.2649, 3.00
)
SELECT employeeno, [8322.170], [10184.2648], [8321.169], [10184.2649]
FROM PivotData
PIVOT (MAX([hour_per_costcode])
FOR costcoding
IN ([8322.170], [10184.2648], [8321.169], [10184.2649])
) AS PivotResult
ORDER BY employeeno;
Result:
employeeno 8322.170 10184.2648 8321.169 10184.2649
---------- ---------- ------------ ---------- -----------
PH080418 10.00 1.50 NULL NULL
PH080441 6.50 NULL 1.00 3.00

Recursive Common Table Expression

I know I am probably going about this the wrong way, but I am trying to understand Recursive CTE's.
I created a simple table
RowNum Type Amount
1 Anch 10
2 Amt 1
3 Amt 2
4 Amt 3
5 Amt 4
The idea was to anchor at the amount 10, the to recursively loop through and remove the amount from the total.
I came up with below
WITH cte_Rec (RowNum, [Type], Amount, Amount2, RT, RN)
AS (SELECT RowNum,
[Type],
Amount,
Amount,
Amount,
RowNum
FROM dbo.tbl_RecursiveCTE
WHERE [Type] = 'Anch'
UNION ALL
SELECT r.RowNum,
r.[Type],
r.Amount,
ct.Amount,
ct.Amount - r.Amount AS RT,
ct.RowNum
FROM dbo.tbl_RecursiveCTE r
INNER JOIN cte_Rec ct
ON ct.RowNum = r.RowNum - 1)
SELECT *
FROM cte_Rec
Which obv does not work.
Any ideas?
Not sure what doesn't work for you and what exactly you really want .....
But something like this should work:
;WITH cte_Rec AS
(
SELECT RowNum, RowType, Amount AS 'Amount', Amount AS 'SumAmt'
FROM dbo.tbl_RecursiveCTE
WHERE RowType = 'Anch'
UNION ALL
SELECT r.RowNum, r.RowType, r.Amount, CAST(ct.SumAmt - r.Amount AS DECIMAL(18,2))
from dbo.tbl_RecursiveCTE r
INNER JOIN cte_Rec ct on ct.RowNum = r.RowNum - 1
)
SELECT *
FROM cte_Rec
I get an output of:
RowNum RowType Amount SumAmt
1 Anch 10.00 10.00
2 Amt 1.00 9.00
3 Amt 2.00 7.00
4 Amt 3.00 4.00
5 Amt 4.00 0.00
The Amount row shows the amount for that specific row, while SumAmt starts with the 10.00 and then consecutively subtracts the other amounts - is that what you're looking for??