PivotTable issue on sqlserver- Data getting split to multiple rows - sql-server

I performed a Pivot on an existing table to get the Week data on the Column Titles, however instead of consolidating and giving me the data in just 3 rows, it splitting to multiple rows.
I am looking to see the data in just 3 rows and not the repetition.
Please let me know how to g about with this.
This is the query (looks a little messy coz of the details hidden)
This is the data I get with the Unpivot:
Expected result after the Pivot is:

I have done what I can based on your redacted SQL statement. You just need to group on Department and Type, then aggregate the pivoted values
select case when [REDACTED] END as Dept, Type, max([2019W01]) as [2019W01], max([2019W02]) as [2019W02], max([2019W03]) as [2019W03], max([2019W04]) as [2019W04]
from ( select
ltrim(rtrim(Plant)) as Plant
,cast(ltrim(rtrim(WeekNo)) as varchar) as WeekNo
,substring(cast(ltrim(rtrim(WeekNo)) as [REDACTED]
from [REDACTED] ) as a
unpivot
(Value for Type in (A,B,C)) as sq
pivot (
min(Value)
for WeekNo in ([2019W01], [2019W02], [2019W03], [2019W04])
) as Pvt
group by Dept, Type

This seems a lot clearer to me when pivoting data. You only need to copy-paste-replace on one place and you define how you group your columns.
SELECT Dept, Type,
MIN(CASE WHEN Weekno = '2019W01' THEN [value] END),
MIN(CASE WHEN Weekno = '2019W02' THEN [value] END),
MIN(CASE WHEN Weekno = '2019W03' THEN [value] END),
MIN(CASE WHEN Weekno = '2019W04' THEN [value] END),
MIN(CASE WHEN Weekno = '2019W05' THEN [value] END),
MIN(CASE WHEN Weekno = '2019W06' THEN [value] END)
FROM SomeTable
GROUP BY Dept, Type
ORDER BY Dept, Type;

Related

multiple column pivot in sql server

I have some issue about how to make query result like
this is what i've tried,, but not exactly same like what i mean
CREATE TABLE #dta
(
Data [nvarchar](max),
Date [varchar] (12) ,
GR [int] ,
Refund [int] ,
Sales [int] ,
)
INSERT INTO #dta
SELECT 'asd',1,10,0,0 UNION ALL
SELECT 'asd',2,0,0,4 UNION ALL
SELECT 'asd',3,4,1,1 UNION ALL
SELECT 'qwe',1,2,0,0 UNION ALL
SELECT 'qwe',3,0,0,1 UNION ALL
SELECT 'zxc',1,0,0,5 UNION ALL
SELECT 'zxc',2,4,0,1 UNION ALL
SELECT 'zxc',3,0,1,5
--Only for sales
SELECT data, [1],[2],[3] FROM
(SELECT data, [date] , Sales FROM #dta )Tab1
PIVOT
(
SUM(Sales) FOR [date] IN ([1],[2],[3])) AS Tab2
ORDER BY Tab2.Data
You can use conditional aggregation and try something along this code:
SELECT t.[Data]
,MAX(CASE WHEN t.[Date]=1 THEN t.Sales END) AS [Sales_Date_1]
,MAX(CASE WHEN t.[Date]=1 THEN t.Refund END) AS [Refund_Date_1]
,MAX(CASE WHEN t.[Date]=1 THEN t.GR END) AS [GR_Date_1]
,MAX(CASE WHEN t.[Date]=2 THEN t.Sales END) AS [Sales_Date_2]
,MAX(CASE WHEN t.[Date]=2 THEN t.Refund END) AS [Refund_Date_2]
,MAX(CASE WHEN t.[Date]=2 THEN t.GR END) AS [GR_Date_2]
,MAX(CASE WHEN t.[Date]=3 THEN t.Sales END) AS [Sales_Date_3]
,MAX(CASE WHEN t.[Date]=3 THEN t.Refund END) AS [Refund_Date_3]
,MAX(CASE WHEN t.[Date]=3 THEN t.GR END) AS [GR_Date_3]
FROM #dta t
GROUP BY t.[Data];
If the count of t.[Date] (1 to 3 in your example data) is not limited to a known maximum, you'd have to create the statement dyanmically.
If your t.[Date] column is a date value actually and you want your output columns named after some date values (unpredictable column alias) within your set, you must create this dynamically too.

How to use Pivot with RowNumber and date

I have a SQL Server table like this:
How can I change reading column into 2 columns based on rownumber?
I have tried like this:
WITH pivot_data AS
(
SELECT
date, CurrentMeterSNID,
1 + ((ROW_NUMBER() OVER (PARTITION BY CurrentMeterSNID ORDER BY date desc) - 1) % 2) rownum,
Reading
FROM
INF_Facility_ElectricalRecord
)
SELECT
date, CurrentMeterSNID, [1], [2]
FROM
pivot_data
PIVOT
(MAX(Reading) FOR rownum IN ([1], [2])) AS p;
but the result that I get is:
I get Null record; how can I replace that null value with record from a day after the date?
actually you are not doing PIVOT. You just want to conditionally display the value on different column. For this you use the CASE statement.
For the second requirement : for the NULL value, showing subsequent day value, you can use LEAD() or LAG() window function. This is the else part of the case
select date, CurrentMeterSNID,
[1] = case when rownum2 = 1
then reading
else lead(reading) over(partition by CurrentMeterSNID order by date)
end,
[2] = case when rownum2 = 2
then reading
else lead(reading) over(partition by CurrentMeterSNID order by date)
end
from INF_Facility_ElectricalRecord
As long as you are displaying every date in that query, you can't have what you want.
So you have to pick the max(date) in other words where rownumber will be 1.
WITH pivot_data AS(
SELECT date,CurrentMeterSNID,
1 + ((row_number() over(partition by CurrentMeterSNID ORDER by date desc) - 1) % 2) rownum,
Reading
FROM dbo.Table_1 )
, T2 AS
(
SELECT CurrentMeterSNID, date, [1], [2]
FROM pivot_data PIVOT (max(Reading) FOR rownum IN ([1],[2])) AS p
)
SELECT CurrentMeterSNID, Max(date), MAX([1]), Max([2])
FROM T2
GROUP BY CurrentMeterSNID

TSQL results in specific number of columns

I'm trying to create a query that will distribute the row results in specific number of columns (ex. 4). See below screenshot.
It is presentation matter and it should be handled on application level.
But if you insist:
SELECT column1 = MIN(CASE WHEN grp=1 THEN PartNumber+CHAR(13)+SerialNumber END)
,column2 = MIN(CASE WHEN grp=2 THEN PartNumber+CHAR(13)+SerialNumber END)
,column3 = MIN(CASE WHEN grp=3 THEN PartNumber+CHAR(13)+SerialNumber END)
,column4 = MIN(CASE WHEN grp=4 THEN PartNumber+CHAR(13)+SerialNumber END)
FROM (SELECT *,ROW_NUMBER() OVER(PARTITION BY rn ORDER BY rn) AS grp
FROM (SELECT *,(ROW_NUMBER() OVER(ORDER BY 1/0)-1)/4 AS rn FROM tab)s)sub
GROUP BY rn;
DBFiddle Demo

selecting data which meets 3 criteria between certain dates

I need to select all data for the jobs where it was requested by the same memberID in the same department (dept) and on the same day since the beginning of may. Below is my attempted code however i get:
arithmetic overflow error converting expression to data type datetime
I am unsure how to solve this? maybe there is a better query to execute?
select jobID,
memberID,
dept,
[BriefDate],
schemeID from (
Select jobID,
memberID,
dept,
[BriefDate],
schemeID,
RowCnt = Count(*) over(partition by MemberId, Dept, Convert(date, [briefdate]))
from [SSRSReports].[dbo].[corporatejobreportdetailed]
where [BriefDate]>20170501 ) a
Where a.RowCnt >= 3

Does PIVOT automatically take averages of non-aggregated columns?

I have the following working query but I was wondering if I could simplify it using PIVOT:
SELECT P.Date,
P.OI AS [Total Puts],
C.OI AS [Total Calls],
P.[Index Level]
FROM (SELECT Date,
SUM(OpenInterest) AS OI,
AVG(TheSpot) AS [Index Level]
FROM Fullstats
WHERE theType = 'P'
and Code = 'ALSI'
GROUP BY Date) AS P
JOIN (SELECT Date,
SUM(OpenInterest) AS OI
FROM Fullstats
WHERE theType = 'C'
and Code = 'ALSI'
GROUP BY Date) AS C
ON P.Date = C.Date
ORDER BY Date
I can get the first 3 columns easily:
SELECT [Date],
P AS [Total Puts],
C AS [Total Calls]
FROM (SELECT Date,
OpenInterest,
theType
FROM FullStats
WHERE Code = 'ALSI') AS SourceTable
PIVOT
(
SUM(OpenInterest)
FOR theType IN (P, C)
) AS PivotTable
ORDER BY Date;
but I wasn't sure how to get that fourth (AVG(TheSpot) AS [Index Level]) column. So I played around a bit and found that the following works:
SELECT [Date],
P AS [Total Puts],
C AS [Total Calls],
theSpot
FROM (SELECT Date,
OpenInterest,
theType,
theSpot
FROM FullStats
WHERE Code = 'ALSI' AND theType <> 'F') AS SourceTable
PIVOT
(
SUM(OpenInterest)
FOR theType IN (P, C)
) AS PivotTable
ORDER BY Date;
But I don't understand why this is giving me the average of the theSpot column? Is that a feature of PIVOT that it returns the average for any field not aggregated? Could I have gotten the SUM or MIN instead? Lastly how would I ascertain which of these two queries is more efficient?
Not aggregating does not give you the average of "TheSpot" It might be that the value you take comes from a view that aggregates and somehow you lucked out on this. Check out the query below for a way to get the average.
create table pivot_demo (
Id int identity(1,1)
, Value1 decimal
, Value2 decimal
, SetKey int)
insert pivot_demo (Value1, Value2, SetKey) values
(10,10,1),
(20,20,1),
(30,30,1),
(40,40,1),
(50,50,1),
(60,60,1),
(10,10,2),
(20,20,2),
(30,30,2),
(40,40,3),
(50,50,3),
(60,60,3)
select value2, [1], [2], [3] from (
select value1, avg(value2) value2, setkey
from demo..pivot_demo
group by Value1, SetKey) sub
pivot (sum(value1) for setkey in ([1], [2], [3])) piv

Resources