Pivot table missing data in sum in SQL Server - sql-server

I have the following reference table:
CompanyId ProductType ProductCount ProductBought
3 1 12 12
3 2 5 5
3 4 5 5
Then I'm pivoting the table by ProductType:
SELECT
CompanyId,
SUM(ProductBought) AS ProductBought
SUM(ISNULL([1], 0)) AS [1],
SUM(ISNULL([2], 0)) AS [2],
SUM(ISNULL([3], 0)) AS [3],
SUM(ISNULL([4], 0)) AS [4]
FROM (
SELECT * FROM #ReferenceTable
) AS a
PIVOT (
SUM([ProductCount]) FOR ProductType IN ([1], [2], [3], [4])
) as pvt
GROUP BY pvt.CompanyId
This gives the following result:
CompanyId ProductBought 1 2 3 4
3 17 12 5 0 5
I expect the ProductBought value to be 22, so in the pivot, five are going missing.
How can I achieve the full count of ProductBought with the pivot table?

In your query amounts are grouping up based on ProductBrought column. Since for both ProductType 2,4 ProductBrought values are 5 . The data gets grouped up on one single 5 . Just separate them with a simple Row Id column and try.
SELECT * INTO #TEMP FROM
(
SELECT 3 companyId, 1 ProductType,12 ProductCount,12 ProductBought
UNION ALL
SELECT 3, 2,5 ,5 UNION ALL
SELECT 3, 4,5 ,5
)
AS A
Query
SELECT SUM(ProductBought)ProductBought,SUM([1]) [1],SUM([2])[2],SUM([3])[3],SUM([4])[4]
FROM (
SELECT ROW_NUMBER()OVER(PARTITION BY companyId ORDER BY (SELECT 1 )DESC)RN,* FROM #TEMP
) AS A
PIVOT ( SUM( ProductCOUNT ) FOR ProductType IN([1],[2],[3],[4])
)AS B
GROUP BY COMPANYID

Try This
;WITH CTE(CompanyId, ProductType, ProductCount, ProductBought)
AS
(
SELECT 3, 1,12,12 UNION ALL
SELECT 3, 2,5 ,5 UNION ALL
SELECT 3, 4,5 ,5
)
SELECT CompanyId,
ProductBought,
ISNULL(SUM([1]),0) AS [1],
ISNULL(SUM([2]),0) AS [2],
ISNULL(SUM([3]),0) AS [3],
ISNULL(SUM([4]),0) AS [4]
FROM
(
SELECT CompanyId,
ProductType,
ProductCount,
SUM(ProductBought)OVER(ORDER BY CompanyId) AS ProductBought
FROM CTE
)AS SRC
PIVOT
(
SUM(ProductCount) FOR ProductType IN ([1],[2],[3],[4])
)
AS PVT
GROUP BY CompanyId,
ProductBought
Result
CompanyId ProductBought 1 2 3 4
------------------------------------------------
3 22 12 5 0 5

You can sum separately and join with pivot results as below.
SELECT MainTable.CompanyId, MainTable.ProductBought, PivotTable.[1], PivotTable.[2],
PivotTable.[3], PivotTable.[4]
FROM
(
SELECT ReferenceTable.CompanyId, SUM(ProductBought) AS ProductBought FROM
ReferenceTable
GROUP BY CompanyId
) MainTable
INNER JOIN
(
SELECT
CompanyId,
SUM(ISNULL([1], 0)) AS [1],
SUM(ISNULL([2], 0)) AS [2],
SUM(ISNULL([3], 0)) AS [3],
SUM(ISNULL([4], 0)) AS [4]
FROM (
SELECT * FROM dbo.ReferenceTable
) AS a
PIVOT (
SUM([ProductCount]) FOR ProductType IN ([1], [2], [3], [4])
) as pvt
GROUP BY pvt.CompanyId
) PivotTable
ON PivotTable.CompanyId = MainTable.CompanyId

Related

SQL Self Join / Pivot table query

I have the following Table1 in SQL Server 2016:
SELECT Year, Type, Value From Table1
Year Type Value
2010 1 10
2010 2 15
2010 3 20
2011 1 100
2011 2 150
2011 3 200
I would like to convert it to the following table:
Year Type1 Type2 Type3
2010 10 15 20
2011 100 150 200
I think we can do either self join or pivot table to achieve this. What is the best way to achieve this?
CREATE TABLE #myTable (
[Year] int, [Type] int, [Value] int, [ExtraColumn] varchar(10));
INSERT INTO #myTable ([Year], [Type], [Value], [ExtraColumn])
VALUES (2010, 1, 10, 'I'),
(2010, 2, 15, 'G'),
(2010, 3, 20, 'N'),
(2011, 1, 100, 'O'),
(2011, 2, 150, 'R'),
(2011, 3, 200, 'E');
select Year, [1] as Type1, [2] as Type2, [3] as Type3
from (
select [Year], [Type], [Value]
from #myTable
) t
PIVOT ( SUM(Value) FOR [Type] IN ( [1], [2], [3] ) ) pvt;
-- OR
with myData as
(
select [Year], [Type], [Value]
from #myTable
)
select Year, [1] as Type1, [2] as Type2, [3] as Type3
from myData
PIVOT ( SUM(Value) FOR [Type] IN ( [1], [2], [3] ) ) pvt;
drop table #myTable;
Assuming you always have 3 types using conditional aggregation is a simple way to tackle this.
select [Year]
, Type1 = Max(case when [Type] = 1 then Value end)
, Type2 = Max(case when [Type] = 2 then Value end)
, Type3 = Max(case when [Type] = 3 then Value end)
from Table1
group by [Year]
order by [Year]
select *
from myTable PIVOT ( SUM(Value) FOR [Type] IN ( [1], [2], [3] ) ) pvt;
DbFiddle demo
Assuming you always have 3 types, you can use PIVOT in SQL.
Here is an example based on your example:
if object_id('tempdb..#temp1') is not null
drop table #temp1
create table #temp1 (
Year int
,Type int
,Value int
)
insert into #temp1 values
(2010,1,10),
(2010,2,15),
(2010,3,20),
(2011,1,100),
(2011,2,150),
(2011,3,200)
SELECT
Year
, [1] AS Type1
, [2] AS Type2
, [3] AS Type3
FROM
#temp1 p
PIVOT
(
sum(value)
FOR type IN
( [1], [2], [3])
) AS pvt
ORDER BY pvt.Year
Here are the results:

sum pivot value in sql server 2008

Select * From
(SELECT convert(varchar,SUM(distance))
As total_distance, DAY(start_time) Days
FROM t1
Where id=6314
And start_time
Between '2018-02-01 18:30:00'
And '2018-02-09 18:00:00'
GROUP BY DAY(start_time)
) d
pivot
(Max(total_distance)
For Days in ([3],[4],[5],[6],[7],[8],[9])
) piv;
results-
3 4 5 6 7 8 9
0 0 50.2 44.32 42.34 43.38 41.32
i want a sum column for these values along with this result like ;-
sum 3 4 5 6 7 8 9
221.56 0 0 50.2 44.32 42.34 43.38 41.32
add the following to your result set of the query: the CROSS APPLY part.
;WITH t ([3] ,[4] ,[5] ,[6] , [7], [8] ,[9]) as
(
SELECT 0 , 0 , 50.2 , 44.32 , 42.34 , 43.38 , 41.32
)
SELECT *
FROM t
CROSS APPLY
(SELECT SUM(x.Val)
FROM
(
VALUES ([3]),([4]),([5]),([6]),([7]),([8]),([9])
) X (VAL)
) P(SVal)
and here is the query with your input:
;WITH Pvt as
(
select * from
(SELECT convert(varchar,SUM(distance)) as total_distance, DAY(start_time) Days
FROM t1
where id=6314 and start_time between '2018-02-01 18:30:00' and '2018-02-09 18:00:00'
GROUP BY DAY(start_time)
) d
pivot
(max(total_distance)
for Days in ([3],[4],[5],[6],[7],[8],[9])
) piv
)
SELECT *
FROM Pvt
CROSS APPLY
(SELECT SUM(x.Val)
FROM
(
VALUES ([3]),([4]),([5]),([6]),([7]),([8]),([9])
) X (VAL)
) P(SVal)

T-SQL Cumulative Count Reset per Month

I need to count cumulative count in T-SQL. This can be done as:
WITH DATASET AS (SELECT '2014-01-28' AS [DATE], 1 AS [COUNT]
UNION
SELECT '2014-01-29' AS [DATE], 5 AS [COUNT]
UNION
SELECT '2014-01-30' AS [DATE], 15 AS [COUNT]
UNION
SELECT '2014-01-31' AS [DATE], 4 AS [COUNT]
UNION
SELECT '2014-02-01' AS [DATE], 7 AS [COUNT]
UNION
SELECT '2014-02-02' AS [DATE], 1 AS [COUNT]
)
, CTE AS (SELECT *
,ROW_NUMBER() OVER (ORDER BY [DATE]) ROWNUM
FROM DATASET
)
SELECT CTE1.[DATE]
,CTE1.[COUNT]
,SUM(CTE2.[COUNT]) AS CUM_CNT
FROM CTE CTE1
JOIN CTE CTE2 ON CTE2.ROWNUM <= CTE1.ROWNUM
GROUP BY CTE1.[DATE]
,CTE1.[COUNT]
That returns:
DATE COUNT CUM_CNT
2014-01-28 1 1
2014-01-29 5 6
2014-01-30 15 21
2014-01-31 4 25
2014-02-01 7 32
2014-02-02 1 33
But I want to reset the cumulative count per each month so the data returned should be:
DATE COUNT CUM_CNT
2014-01-28 1 1
2014-01-29 5 6
2014-01-30 15 21
2014-01-31 4 25
2014-02-01 7 7
2014-02-02 1 8
Is it possible to achieve this in T-SQL? How?
As of SQL Server 2012+ you can use window version of SUM to calculate running totals. You just have to PARTITION by YEAR([DATE]), MONTH([DATE]) to get the expected result:
WITH DATASET AS (
SELECT '2014-01-28' AS [DATE], 1 AS [COUNT]
UNION
SELECT '2014-01-29' AS [DATE], 5 AS [COUNT]
UNION
SELECT '2014-01-30' AS [DATE], 15 AS [COUNT]
UNION
SELECT '2014-01-31' AS [DATE], 4 AS [COUNT]
UNION
SELECT '2014-02-01' AS [DATE], 7 AS [COUNT]
UNION
SELECT '2014-02-02' AS [DATE], 1 AS [COUNT]
)
SELECT [DATE], [COUNT],
SUM([COUNT]) OVER (PARTITION BY YEAR([DATE]), MONTH([DATE])
ORDER BY [DATE]) AS CUM_CNT
FROM DATASET
SQL Fiddle Demo
SELECT '2014-01-28' AS [DATE], 1 AS [COUNT]
UNION
SELECT '2014-01-29' AS [DATE], 5 AS [COUNT]
UNION
SELECT '2014-01-30' AS [DATE], 15 AS [COUNT]
UNION
SELECT '2014-01-31' AS [DATE], 4 AS [COUNT]
UNION
SELECT '2014-02-01' AS [DATE], 7 AS [COUNT]
UNION
SELECT '2014-02-02' AS [DATE], 1 AS [COUNT]
)
Select C2.date,sum(c1.count) as COUNT, sum(distinct c2.count) AS CUML_COUNT from DATASET C1
JOIN DATASET C2 ON month(C1.date) = month(C2.date) and C1.Date <= C2.Date
group by C2.date

How to use pivot in this table

Actual Table Structure
===================================
slno ParnetID ParnetName Promotion Marketer
1 SLM1010S SKR.RAJASHEGARAN 2 43640
2 40049 M.KANNAN 3 43640
3 40018 M.PRABU 6 43640
4 SLM1010S SKR.RAJASHEGARAN 2 43641
5 40042 M.KANNAN 3 43641
6 40011 M.PRABU 6 43641
i have my query :
WITH temp
AS (SELECT slno,
parentid,
parentname,
parentpromotionid,
marketerid,
(SELECT Count(*)
FROM parentmaster
WHERE t1.marketerid = marketerid
AND t1.parentid = parentid
AND t1.parentname = parentname
AND slno <= t1.slno) AS RowNum
FROM parentmaster AS t1)
SELECT marketerid,
[2],
[6],
[3]
FROM temp
PIVOT ( Min(parentid)
FOR parentpromotionid IN ([2],
[6],
[3]) ) AS t
But I want This Table Structure
MarketerID 2 6 3
43640 SLM1010S 40018 40049
43641 SLM1010S 40011 40042
This may help u..
select marketer,[2],[3],[6] from
(
select Marketer,Promotion,ParnetID
from parentmaster
) d pivot (min(ParnetID) for Promotion in ([2],[3],[6])) as pvt
try this,
Declare #t table(slno int,ParnetID varchar(50),ParnetName varchar(50),Promotion int,Marketer int)
insert into #t
select 1,'SLM1010S','SKR.RAJASHEGARAN', 2, 43640 union all
select 2,'40049','M.KANNAN', 3, 43640 union all
select 3,'40018', 'M.PRABU', 6, 43640 union all
select 4,'SLM1010S', 'SKR.RAJASHEGARAN', 2, 43641 union all
select 5,'40042', 'M.KANNAN', 3, 43641 union all
select 6,'40011', 'M.PRABU', 6, 43641
select distinct a.Marketer,b.ParnetID ,c.ParnetID,d.ParnetID from #t a
left join #t b on a.Marketer=b.Marketer and b.promotion=2
left join #t c on a.Marketer=c.Marketer and c.promotion=3
left join #t d on a.Marketer=d.Marketer and d.promotion=6
select Marketer, [0],[1],[2],[3],[4],[5],[6]
from (
select Marketer,Promotion,ParnetID
from #t
) d
pivot
(
MIN(ParnetID)
FOR Promotion
IN ([0],[1],[2],[3],[4],[5],[6])
) as TST

Make Total in Pivot Query

Below is my query
SELECT UserName ,
TotCount ,
EntryDate
FROM #CandidateCount AS cc
and output of above query is
UserName TotCount EntryDate
--------------------------------
neelam 2 17/12/2013
neelam 1 18/12/2013
neelam 6 19/12/2013
snehal 7 17/12/2013
snehal 0 18/12/2013
snehal 2 19/12/2013
I have updated above query
SELECT *
FROM ( SELECT EntryDate ,
UserName ,
TotCount
FROM #CandidateCount AS tbl
) AS SourceTable PIVOT
( SUM(TotCount) FOR UserName IN ( [neelam], [snehal] ) )AS PivotTable
ORDER BY EntryDate DESC
and output of above query is
EntryDate neelam snehal
19/12/2013 6 2
18/12/2013 1 0
17/12/2013 2 7
Now i want to make total datewise like this
EntryDate neelam snehal Total
19/12/2013 6 2 8
18/12/2013 1 0 1
17/12/2013 2 7 9
How can i do this? Thanks.
I've put your data inside a CTE named Source to give you an example. With another CTE you can easily put your totals aside. You can later join these totals on both EntryDates:
WITH Source AS (
SELECT 'neelam' AS UserName, 2 AS TotCount, '17/12/2013' AS EntryDate UNION
SELECT 'neelam' AS UserName, 1 AS TotCount, '18/12/2013' AS EntryDate UNION
SELECT 'neelam' AS UserName, 6 AS TotCount, '19/12/2013' AS EntryDate UNION
SELECT 'snehal' AS UserName, 7 AS TotCount, '17/12/2013' AS EntryDate UNION
SELECT 'snehal' AS UserName, 0 AS TotCount, '18/12/2013' AS EntryDate UNION
SELECT 'snehal' AS UserName, 2 AS TotCount, '19/12/2013' AS EntryDate
)
, Totals AS (
SELECT EntryDate
, SUM(TotCount) AS Total
FROM Source
GROUP BY EntryDate
)
SELECT PivotTable.*
, Totals.Total
FROM ( SELECT EntryDate ,
UserName ,
TotCount
FROM Source AS tbl
) AS SourceTable PIVOT
( SUM(TotCount) FOR UserName IN ( [neelam], [snehal] ) )AS PivotTable
JOIN Totals ON PivotTable.EntryDate = Totals.EntryDate
ORDER BY PivotTable.EntryDate DESC
In your exact case:
WITH Totals AS (
SELECT EntryDate
, SUM(TotCount) AS Total
FROM #CandidateCount
GROUP BY EntryDate
)
SELECT PivotTable.*
, Totals.Total
FROM ( SELECT EntryDate ,
UserName ,
TotCount
FROM #CandidateCount AS tbl
) AS SourceTable PIVOT
( SUM(TotCount) FOR UserName IN ( [neelam], [snehal] ) )AS PivotTable
JOIN Totals ON PivotTable.EntryDate = Totals.EntryDate
ORDER BY PivotTable.EntryDate DESC

Resources