Pivot table from horizontal to vertical - sql

i have a following table of results:
What i want is a resulted table with following structure:
Is any posibility to do that with SQL?
Thanks in advance.
EDIT (SQL query with exampled temp table):
CREATE TABLE #FINAL_STACK
(
FB_DATE datetime,
FB_DESC VARCHAR(200)
)
INSERT INTO #FINAL_STACK(FB_DATE, FB_DESC)
SELECT '2017-03-09', 'D - FIZ: 1'
UNION
SELECT '2017-03-09', 'D - PRI: 1'
UNION
SELECT '2017-03-10', 'D - FIZ: 1'
UNION
SELECT '2017-03-10', 'D - PRI: 1'
UNION
SELECT '2017-03-13', 'D - FIZ: 2'
UNION
SELECT '2017-03-13', 'D - PRI: 1'
UNION
SELECT '2017-03-13', 'D - TEPAP: 1'
SELECT * FROM #FINAL_STACK

Try this:
DECLARE #DynammicTSQLStatement NVARCHAR(MAX)
,#DynamicPIVOTColumns NVARCHAR(MAX);
SET #DynamicPIVOTColumns = STUFF
(
(
SELECT ',[' + CAST([FB_DATE] AS VARCHAR(12)) + ']'
FROM #FINAL_STACK
GROUP BY [FB_DATE]
ORDER BY [FB_DATE]
FOR XML PATH('') ,TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
SET #DynammicTSQLStatement = N'
SELECT *
FROM
(
SELECT *
,ROW_NUMBER() OVER (PARTITION BY FB_DATE ORDER BY (SELECT 1)) AS RID
FROM #FINAL_STACK
) DS
PIVOT
(
MAX([FB_DESC]) FOR [FB_DATE] IN (' + #DynamicPIVOTColumns + ')
) PVT';
EXEC sp_executesql #DynammicTSQLStatement;
We need to perform dynamic pivot in order to be sure it will always work for different days. Also, note we are creating a row ID column using ROW_NUMBER in order to ensure all records for particular date are displayed. Otherwise, you will get only one value (for example the min or the max) depending on the PIVOT aggregate function.

Related

show results in a Pivot way (no aggregate)

i've searched all over for an answer for this, and couldn't really find anything useful,
im pretty much a begginer in Sql so maybe i'm missing something basic
i have a simple table with 2 columns : line, fullname
this is the query i use :
SELECT
(select distributionline from extrasums where key=accounts.accountkey and SuFID='63') as 'line',
fullname
FROM
accounts
ORDER BY
(select distributionline from extrasums where key=accounts.accountkey and SuFID='63'),
(select dotinline from extrasums where key=accounts.accountkey and SuFID='68')
these are the results i get : (not allowed to embed images)
basically i get the distribution lines and the costumers, and the tables is ordered by the dist.lines and the place in line of each costumer.
all i want to do is show these results in a pivot-table style
i tried "pivot" but i understand you cant pivot without aggregate, because thats the whole point of "pivot" in sql.
this is what i want to achieve :
basically the dist.lines are the column names and the results are orders in a pivot way
the dist.lines are not permanent, one day we can have 3 lines. the other we can have 10 lines. its dynamic based on the deliveries for tomorrow. obviously.
same with the costumers.
you're welcome:
DROP TABLE IF EXISTS #temp;
SELECT RANK() OVER (PARTITION BY a.LINE ORDER BY a.fullname) AS rownum, a.line, a.fullname
INTO #temp
FROM ( SELECT 43 AS line, 'Daniel' AS fullname
UNION ALL
SELECT 43 AS line, 'john' AS fullname
UNION ALL
SELECT 43 AS line, 'kenny' AS fullname
UNION ALL
SELECT 43 AS line, 'adam' AS fullname
UNION ALL
SELECT 55 AS line, 'james' AS fullname
UNION ALL
SELECT 55 AS line, 'jones' AS fullname
UNION ALL
SELECT 68 AS line, 'kelly' AS fullname) AS a;
DECLARE #cols AS NVARCHAR(MAX), #colname AS NVARCHAR(MAX), #query AS NVARCHAR(MAX);
SET #colname = STUFF(( SELECT DISTINCT ',' + QUOTENAME(c.line)
FROM #temp AS c
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
, 1
, 1
, '');
SET #cols = STUFF(( SELECT DISTINCT ',ISNULL(' + QUOTENAME(c.line) + ','''') AS '+QUOTENAME(c.line )
FROM #temp AS c
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
, 1
, 1
, '');
PRINT #cols
PRINT #colname
SET #query =
N'SELECT rownum, ' + #cols
+ N' from
(
select rownum
, fullname
, line
from #temp
) x
pivot
(
max(fullname)
for line in (' + #colname + N')
) p ';
PRINT #query
EXECUTE (#query);
enter image description here

Issue Using PIVOT in SQL

I am trying to use POVIT while looking at this example This
Here is the Code:
CREATE DATABASE DEMO
GO
 
USE DEMO
GO
 
-- Creating table for demo
IF (object_id('TblPivot','U') > 0)
DROP TABLE TblPivot
 
CREATE TABLE TblPivot
(
ItemCode int,
ItemName varchar(100),
ItemColour varchar(50)
)
GO
 
-- Inerting some sample records
INSERT INTO TblPivot
SELECT 1,'Samsung Mobile','Red'
UNION ALL
SELECT 2,'Nokia Mobile','Blue'
UNION ALL
SELECT 3,'Nokia Mobile','Green'
UNION ALL
SELECT 4,'Motorola Mobile','Red'
UNION ALL
SELECT 5,'Samsung Mobile','Green'
UNION ALL
SELECT 2,'Nokia Mobile','Blue'
UNION ALL
SELECT 1,'Samsung Mobile','Red'
UNION ALL
SELECT 2,'Nokia Mobile','Blue'
GO
And here is the PIVOT selection
-- Getting table data
SELECT
ItemCode,
ItemName,
ItemColour
from TblPivot
GO
-- Getting agreegated data using Pivot and converted rows to column
SELECT
*
FROM
(
SELECT
ItemCode,
ItemName,
ItemColour
FROM TblPivot
) AS P
PIVOT
(
Count(ItemName) FOR ItemColour IN (Red, Blue, Green)// Here is the Issue
where it knows what words to give it like Red,Blue,Green what I want is to use
what ever the ItemColur it could be 100s What ever you get
from the data base use that for the `IN(ItemColur)`
) AS pv
GO
It keeps saying that The column name "ItemColur" specified in the PIVOT operator conflicts with the existing column name in the PIVOT argument.
How can I get this working with that I even tried to make a Temp Table didn't work
This is the code for dynamic PIVOT:
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += N', p.' + QUOTENAME(ItemColour)
FROM (SELECT distinct p.ItemColour FROM dbo.TblPivot AS p
) AS x;
SET #sql = N'
SELECT itemcode, ' + STUFF(#columns, 1, 2, '') + '
FROM
(
SELECT p.itemcode, p.ItemName, p.ItemColour
FROM dbo.TblPivot AS p
) AS j
PIVOT
(
COUNT(ItemName) FOR ItemColour IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+ ')
) AS p;';
PRINT #sql;
EXEC sp_executesql #sql;
The output for above query looks like this:

Pivot multiple columns in SQL Server 2008

I am trying to convert column to rows. I am beginner to PIVOT. Tried below code but error is coming as 'Error converting data type nvarchar to datetime.
The incorrect value "Tot_GPS_Cnt" is supplied in the PIVOT operator.'
CREATE TABLE #tbl_Res1
(
CallDate DATETIME,
Tot_GPS_Cnt INT,
Tot_GND_Cnt INT,
Per_Ratio NUMERIC(10,2)
)
INSERT INTO #tbl_Res1
SELECT '2015-04-24 00:00:00.000','40','26','65.00' UNION ALL
SELECT '2015-04-25 00:00:00.000','22','14','63.64' UNION ALL
SELECT'2015-04-26 00:00:00.000','27','21','77.78' UNION ALL
SELECT'2015-04-27 00:00:00.000','41','23','56.10'
Source Table
Desired Output
I have tried with below query bu failing. Please help. Thanks in advance
SELECT CallDate=col, Tot_GPS_Cnt, Tot_GND_Cnt, Per_Ratio
FROM
( select CallDate, col, value from #tbl_Res1
cross apply
(
SELECT 'Tot_GPS_Cnt',cast(Tot_GPS_Cnt as varchar(10)) UNION ALL
SELECT 'Tot_GND_Cnt', cast(Tot_GND_Cnt as varchar(10)) UNION ALL
SELECT 'Per_Ratio', cast(Per_Ratio as varchar(10))
) c (col,value)
) d
PIVOT
(
max(value) for CallDate in ([Tot_GPS_Cnt], [Tot_GND_Cnt], [Per_Ratio])
) as piv
The correct syntax for PIVOT is:
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
Hence, you have to place date values not [Tot_GPS_Cnt], [Tot_GND_Cnt], [Per_Ratio] in place of pivoted columns:
SELECT CallDate=col, [2015-04-24], [2015-04-25], [2015-04-26], [2015-04-27]
FROM
( select CallDate, col, value from #tbl_Res1
cross apply
(
SELECT 'Tot_GPS_Cnt',cast(Tot_GPS_Cnt as varchar(10)) UNION ALL
SELECT 'Tot_GND_Cnt', cast(Tot_GND_Cnt as varchar(10)) UNION ALL
SELECT 'Per_Ratio', cast(Per_Ratio as varchar(10))
) c (col,value)
) d
PIVOT
(
max(value) for CallDate in ([2015-04-24], [2015-04-25], [2015-04-26], [2015-04-27])
) as piv
Thank you #Giorgos Betsos. I just made dynamic solution. Just wanted to share with all.
DECLARE #coldata VARCHAR(500);
DECLARE #sql VARCHAR(MAX);
SELECT #coldata = COALESCE(#coldata + '], [', '') + CONVERT(VARCHAR(10),calldate,110)
FROM #tbl_Res1;
SELECT #coldata = '[' + #coldata +']';
SELECT #coldata;
SET #sql = 'SELECT CallDate=col, ' + #coldata + '
FROM
( SELECT CallDate, col, value FROM #tbl_Res1
cross apply
(
SELECT ''Tot_GPS_Cnt'', CAST(Tot_GPS_Cnt as VARCHAR(10)) UNION ALL
SELECT ''Tot_GND_Cnt'', CAST(Tot_GND_Cnt as VARCHAR(10)) UNION ALL
SELECT ''Per_Ratio'', CAST(Per_Ratio as VARCHAR(10))
) c (col,value)
) d
PIVOT
(
MAX(value) FOR CallDate IN (' + #coldata + ')
) as piv'
SELECT #sql;
EXECUTE (#SQL);

Dynamic pivot query in sql server

I have a functioning pivot query for static column values which i want to convert for dynamic column values.
The query is :
with a as (
select request_id, dateadd(month,datediff(month,0,logged_datetime),0) as 'Month'
,dateadd(month,datediff(month,0,logged_datetime),0) as 'Year'
from requests
)
select * from (
select datepart(m,a.Month) as 'months',datepart(YEAR,a.Year) as 'years',a.request_id
from a ) ps
pivot (
count(request_id) for [years] in ([2008],[2009],[2010],[2011],[2012],[2013],[2014],[2015])
) as pvt
order by months
For the dynamic query written below I am getting errors like
Msg 207, Level 16, State 1, Line 5 Invalid column name '2010'. :
select distinct datepart(year,dateadd(month,datediff(month,0,logged_datetime),0)) as 'Yearz'
into #t
FROM requests
DECLARE #Dynamic AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
SELECT #ColumnName= ISNULL(#ColumnName + ',','')
+ QUOTENAME(Yearz)
FROM (SELECT * from #t) AS Yea
SET #Dynamic =
N'
select * from (
select datepart(m,dateadd(month,datediff(month,0,logged_datetime),0)) as months,' + #ColumnName + ',request_id
from requests ) ps
pivot (
count(request_id) for [Years] in (' + #ColumnName + ')
) as pvt
order by months
'
EXEC sp_executesql #Dynamic
SAMPLE TABLE
SELECT * INTO #REQUESTS
FROM
(
SELECT 1 request_id, '2012-06-01' logged_datetime
UNION ALL
SELECT 2 request_id, '2012-05-01'
UNION ALL
SELECT 11 request_id, '2012-06-01'
UNION ALL
SELECT 12 request_id, '2012-05-01'
UNION ALL
SELECT 3 request_id, '2012-07-01'
UNION ALL
SELECT 4 request_id, '2013-09-01'
UNION ALL
SELECT 5 request_id, '2013-10-01'
UNION ALL
SELECT 6 request_id, '2014-01-01'
UNION ALL
SELECT 7 request_id, '2014-02-01'
UNION ALL
SELECT 8 request_id, '2014-03-01'
UNION ALL
SELECT 9 request_id, '2014-05-01'
UNION ALL
SELECT 10 request_id, '2015-11-01'
)TAB
QUERY
Get the column for years and order it in numeric order
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + CAST([YEAR] AS VARCHAR(4)) + ']', '[' + CAST([YEAR] AS VARCHAR(4)) + ']')
FROM (SELECT DISTINCT YEAR(dateadd(month,datediff(month,0,logged_datetime),0)) [YEAR] FROM #REQUESTS) PV
ORDER BY CAST([YEAR] AS INT)
Now pivot the query
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT * FROM
(
-- We will get the count for a year and number of request_id in that month here as CNT column
select DISTINCT datepart(m,a.Month) as ''months'',datepart(YEAR,a.Year) as ''years'',
COUNT(*) OVER(PARTITION BY datepart(YEAR,a.Year),datepart(m,a.Month)) CNT
from
(
select request_id, dateadd(month,datediff(month,0,logged_datetime),0) as ''Month''
,dateadd(month,datediff(month,0,logged_datetime),0) as ''Year''
from #requests
)a
) x
PIVOT
(
MIN(CNT)
FOR years IN (' + #cols + ')
) p
ORDER BY MONTHS;'
EXEC SP_EXECUTESQL #query
Click here to view the result
I think you need to wrap your dynamic column names using the QUOTENAME function:
See example here:

Convert a row as column and merge two column as its value

I have stuck in a select statement, converting rows into columns. I have tried with PIVOT, i was able to convert the single column. But my requirement is little different. I have explained the requirement below.
I have a table structure as below,
I want to select the data as below,
The values in the table are dynamic, which is not a problem for me to deal with that. But i need a way to get the below result.
Could someone please give me a hint on doing it, may be a way to modify the PIVOT below.
select *
from
(
select TSID,AID,Count,BID
from tbl TS
WHERE TS.TPID = 1
) src
pivot
(
sum(Count)
for AID in (AID1,AID2,AID3)
) piv
Thank you..
You may check this fiddle
EDIT
This will work for not previously known column names
DECLARE #Columns AS VARCHAR(MAX)
DECLARE #SQL AS VARCHAR(MAX)
SELECT #Columns = STUFF(( SELECT DISTINCT ',' + AID
FROM Table1
FOR
XML PATH('')
), 1, 1, '')
SET #SQL = '
;WITH MyCTE AS
(
SELECT TSID,
AID,
STUFF(( SELECT '','' + CONVERT(VARCHAR,[Count] )
FROM Table1 I Where I.TSID = O.TSID
FOR
XML PATH('''')
), 1, 1, '''') AS CountList
FROM Table1 O
GROUP BY TSID,
AID
)
SELECT *
FROM MyCTE
PIVOT
(
MAX(CountList)
FOR AID IN
(
' + #Columns + '
)
) AS PivotTable'
EXEC(#SQL)