I'm currently working to retrieve the last 6 available dates data using pivot, unpivot. Can anyone help me with this query?
select *
from #myTable
unpivot (value for Area in (abc,def,fgh,ijk,klp)) up
pivot (max(value) for [date] in (
##-- Here I need to get the last 6 available dates less than current date
)) p
Datatype of [Date] column is DATE.
Sample values of date in my db
2017-09-16,
2017-09-09,
2017-09-02,
2017-08-26,
2017-07-22,
2017-07-01,
2017-06-24,
2017-06-11
Sample table, with expected result
Well, from your sample data, the top 6 for one area would be the same for each area since Area is the column names. With that information, we can use a dynamic unpivot after the original pivot.
declare #table table (TheDate date, abc int, def int, fgh int, ijk int, klp int)
insert into #table
values
('20170916',1,2,34,4,5),
('20170909',2,3,4,5,676),
('20170902',6,7,8,8,9)
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
if object_id('tempdb..#staging') is not null drop table #staging
select
Area
,TheDate
,Val
into #staging
from #table
unpivot
(Val for Area in (abc,def,fgh,ijk,klp)
) up
--Get distinct values of the PIVOT Column / top 6 by date
SELECT #ColumnName= ISNULL(#ColumnName + ',','')
+ QUOTENAME(TheDate)
FROM (SELECT DISTINCT TOP 6 TheDate FROM #staging ORDER BY TheDate DESC) AS TheDate
--Prepare the PIVOT query using the dynamic
SET #DynamicPivotQuery =
N'SELECT Area, ' + #ColumnName + '
FROM #staging
PIVOT(SUM(Val)
FOR TheDate IN (' + #ColumnName + ')) AS PVTTable'
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery
See It In Action Here
Related
I have data in current format
and I want to get data through SQL query in
Can some one explain what should I search or how can I write SQL query with this. I'm not an expert in SQL.
You need dynamic pivot query to achieve this. try below query
declare #columns varchar(max)='',#sql nvarchar(max);
Create table #temp (Name nvarchar(max));
insert into #temp select distinct date from YourTable --inert distinct date for pivot column
SELECT #columns+=QUOTENAME(Name) + ',' from #temp
SET #columns = LEFT(#columns, LEN(#columns) - 1);
set #sql='
SELECT * FROM
(
select ID,cast(Status as int) Status,date from YourTable
) t
PIVOT(Max(Status)
FOR date IN ('+#columns+')
) AS pivot_table
'
EXEC (#Sql)
Drop Table #temp
I have such a table with date as column name
but I would like to have these dates in one column in more than one row something like this:
Date Index
20170806 9206
20170813 8041
20170820 8861
20170827 8356
How can I do it in SQL Server
If you would like to go for more dynamic solution rather than hard coding all columns, the below scripts should work:
IF OBJECT_ID('TestTable') IS NOT NULL
DROP TABLE TestTable;
CREATE TABLE TestTable
(
[20170806] INT NOT NULL,
[20170813] INT NOT NULL,
[20170820] INT NOT NULL,
[20170827] INT NOT NULL
)
INSERT INTO TestTable VALUES (9206, 8041, 8861, 8356)
DECLARE #cols NVARCHAR(MAX),
#sql NVARCHAR(MAX)
SELECT #cols = COALESCE(#cols + ',', '') + QUOTENAME(c.COLUMN_NAME)
FROM INFORMATION_SCHEMA.[COLUMNS] AS c
WHERE c.TABLE_NAME = 'TestTable'
SET #sql = '
SELECT [Date],
[Index]
FROM TestTable
UNPIVOT([Index] FOR [Date] IN ('+ #cols +')) AS up'
exec sp_executesql #sql;
You can use UNPIVOT for this.
SELECT * FROM MyTable
UNPIVOT([Date] For [Index] IN( [20170806], [20170813], [20170820], [20170827])) UNPVT
In addition, if you want to make it dynamically, you can use this query too.
DECLARE #ColNames NVARCHAR(MAX)
= STUFF(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
(SELECT T.* FROM (VALUES(1)) AS DUMY(ID) LEFT JOIN MyTable T ON 1=2 FOR XML AUTO, ELEMENTS XSINIL )
,'<T xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">','')
,'</T>','')
,'_x0032_','2')
,' xsi:nil="true"/>','] ')
,'<',',[') ,1,1,'')
DECLARE #SqlQ NVARCHAR(MAX)
= 'SELECT * FROM MyTable UNPIVOT([Date] For [Index] IN( ' + #ColNames + ')) UNPVT'
EXEC sp_executesql #SqlQ
You could use pivot such as:
However, i dont know your exact table names
select field_names
from table_name
pivot
( index
for index in ( Date, Index)
) pivot
but a useful article to follow is
"https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx"
Designed the table (variable) structure as below.
Hopefully, it matches your table structure.
DECLARE #data TABLE
(
[20170806] INT,
[20170813] INT,
[20170820] INT,
[20170827] INT
)
INSERT INTO #data VALUES (9206, 8041, 8861, 8356)
SELECT * FROM #data
You can use UNPIVOT statement for this. If you have dynamic columns, check this.
SELECT [Date],[Index]
FROM
#data
UNPIVOT
(
[Index] FOR [Date] IN ([20170806], [20170813], [20170820], [20170827])
) AS unpivotTable;
and the output is
i have table tbl_product_details like :
create table tbl_product_details (productdate date, productname varchar(100), nav float , ncv float)
insert into tbl_product_details
values('2017-10-04 00:00:00', 'UU8899', 10.23, 13.89),
('2017-10-05 00:00:00', 'UU8899', 12.23, 14.89)
and one master table where name of required pivoting column stored like.
create table dynamiccols(id int , colname varchar(100))
insert into dynamiccols
values(1,'nav'),(1,'ncv')
i need to create dynamic pivoting to show pivoted data for all dates columns along with each column mentioned in dynamiccols
tables like :
productname nav~~04-10-2017 nav~~05-10-2017 ncv~~04-10-2017 ncv~~05-10-2017
UU8899 10.23 12.23 13.89 14.89
i have tried it but not able to make it complete dyanmic for each column in dynamiccols
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName_header AS NVARCHAR(MAX)
DECLARE #ColumnName_pivot AS NVARCHAR(MAX)
declare #kpiname varchar(100)='ncv'
--Get distinct values of the PIVOT Column
SELECT #ColumnName_header= ISNULL(#ColumnName_header + ',','')
+ 'sum('+QUOTENAME(productdate) +') as ' ++QUOTENAME(#kpiname+'~~'+convert(varchar(11),productdate,105)),
#ColumnName_pivot= ISNULL(#ColumnName_pivot + ',','')
+ QUOTENAME(productdate)
FROM (SELECT DISTINCT productdate
FROM tbl_product_details
where productdate between '02-oct-2017' and '05-oct-2017') AS productdate
SET #DynamicPivotQuery =
N' select *
from ( SELECT productname ,' + #ColumnName_header + '
FROM tbl_product_details
PIVOT(sum('+#kpiname+')
FOR productdate IN (' + #ColumnName_pivot + ')) AS PVTTable
group by productname ) '+ char(97)
print #DynamicPivotQuery
exec(#DynamicPivotQuery)
I need to perform some dynamic operation temp table based on some condition.
(add columns based of number and update only those columns)
I have one one master table which contains unit information -
E.G.
ID UNIT
1 kg
2 cm
3 mm
Here, number of rows can vary. It can contain 3 rows or 4 rows or 2 rows.
Now i want create some columns in my temp table based on this.
E.G.
if master table has 2 values then #temp should contain 2 columns as unit1 and unit2.
if 3 values then unit1, unit2 and unit3.
Is it possible? Or do i need to create max number of columns directly in temp table?
Thanks
You have to use Dynamic PIVOT and GLOBAL TEMP TABLE in following:
IF OBJECT_ID('tempdb..#t') IS NOT NULL
DROP TABLE #t
GO
CREATE table #t
(id varchar(max),unit varchar(max))
insert into #t (id,unit)values
(1,'kg'),
(2,'cm'),
(3,'mm'),
(4,'m')
DECLARE #statement NVARCHAR(max)
,#columns NVARCHAR(max)
SELECT #columns = ISNULL(#columns + ',', '') + N'[' + cast(tbl.id as varchar(max)) + ']'
FROM (
SELECT DISTINCT id
FROM #t
) AS tbl
SELECT #statement = 'select *
INTO ##temp
from (
SELECT id,[unit]
FROM #t
) as s
PIVOT
(max(unit) FOR id in(' + #columns + ')) as pvt
'
EXEC sp_executesql #statement = #statement
SELECT * FROM ##temp
DROP TABLE ##temp
I require your kind help on a PIVOT query problem.
The scenario is I have a voting system. Comprises of 3 tables.
Elections, Candidates, Votes.
The PIVOT relates to PIVOTing the Candidate names as Columns and having the VOTE data as the data.
So far I have attemped this and not got it to work, I've gotten into a muddle with it :(
CREATE TABLE #MYELECTIONS (E_POSITION_CODE INT, E_POSITIONNAME VARCHAR(50))
INSERT INTO #MYELECTIONS VALUES (147,'MANAGER')
INSERT INTO #MYELECTIONS VALUES (148,'CHEF')
INSERT INTO #MYELECTIONS VALUES (149,'WAITER')
CREATE TABLE #MYCANDIDATES (C_CANDIDATE_CODE INT,
C_CANDIDATENAME VARCHAR (50), C_POSITION_CODE INT)
INSERT INTO #MYCANDIDATES VALUES (100,'TOM CRUISE', 147)
INSERT INTO #MYCANDIDATES VALUES (101,'MICKY MOUSE', 147)
INSERT INTO #MYCANDIDATES VALUES (103,'DONALD DUCK', 147)
INSERT INTO #MYCANDIDATES VALUES (100,'TOM CRUISE', 148)
CREATE TABLE #MYVOTES (V_POSITION_CODE INT,
V_CANDIDATE_CODE INT, VOTINGPREFERENCE SMALLINT)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,100,1)
INSERT INTO #MYVOTES VALUES (147,101,1)
INSERT INTO #MYVOTES VALUES (147,101,1)
INSERT INTO #MYVOTES VALUES (147,103,1)
INSERT INTO #MYVOTES VALUES (148,100,1)
INSERT INTO #MYVOTES VALUES (148,100,1)
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
DECLARE #MyPositionCode AS INT
SET #MyPositionCode = 147
DECLARE #MyOutput AS NVARCHAR(MAX)
--Get distinct values of the PIVOT Column
SELECT #ColumnName = ISNULL(#ColumnName + ',','')
+ QUOTENAME(C_CANDIDATENAME)
FROM (SELECT TOP 100 PERCENT C_CANDIDATENAME
FROM #MYCANDIDATES
WHERE C_POSITION_CODE = #MyPositionCode
ORDER BY C_CANDIDATE_CODE) AS C_CANDIDATENAME
--Prepare the `PIVOT` query using the dynamic sql
SET #DynamicPivotQuery =
N'SELECT ROW_NUMBER() OVER (ORDER BY E_POSITIONNAME) AS Idnum,
E_POSITIONNAME AS [Position Name], ' + #ColumnName + '
FROM #MYVOTES
INNER JOIN #MYELECTIONS
ON (#MYVOTES.V_POSITION_CODE = #MYELECTIONS.E_POSITION_CODE)
PIVOT(SUM(VOTINGPREFERENCE))
FOR C_CANDIDATENAME IN (' + #ColumnName + ') AS PVTTable
WHERE #MYELECTIONS.E_POSITION_CODE = 147'
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery,
#MyOutput = #MyOutput OUTPUT
SELECT #MyOutput
DROP TABLE #MYELECTIONS
DROP TABLE #MYCANDIDATES
DROP TABLE #MYVOTES
It has to be a dynamic PIVOT as the Candidate Names that I want to Pivot as Columns, could be dynamic depending on how many Candidates there are for an Election position.
The desired output for the above would be like this:-
Election #MyPositionCode = 147
Idnum Position_Name TOM CRUISE MICKY MOUSE DONALD DUCK...
1 MANAGER 4 2 1
Election #MyPositionCode = 148
Idnum Position_Name TOM CRUISE MICKY MOUSE DONALD DUCK...
1 CHEF 2 0 0
Try this
DECLARE #MyPositionCode AS INT
SET #MyPositionCode = 147
Declare the variables for selecting dynamic columns
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + C_CANDIDATENAME + ']', '[' + C_CANDIDATENAME + ']')
FROM
(
SELECT TOP 100 PERCENT C_CANDIDATENAME
FROM #MYCANDIDATES
WHERE C_POSITION_CODE = #MyPositionCode
ORDER BY C_CANDIDATE_CODE
) PV
ORDER BY C_CANDIDATENAME desc
If you want to replace NULL with zero
DECLARE #NulltoZeroCols NVARCHAR (MAX)
SELECT #NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+C_CANDIDATENAME+'],0) AS ['+C_CANDIDATENAME+']'
FROM
(
SELECT TOP 100 PERCENT C_CANDIDATENAME
FROM #MYCANDIDATES
WHERE C_POSITION_CODE = #MyPositionCode
ORDER BY C_CANDIDATE_CODE
)TAB
ORDER BY C_CANDIDATENAME desc FOR XML PATH('')),2,8000)
Now pivot it dynamically. I have written the logic inside
DECLARE #query NVARCHAR(MAX)
SET #query = '-- You can apply ROW_NUMBER() here which is the data after pivot
SELECT ROW_NUMBER() OVER (ORDER BY E_POSITIONNAME) AS Idnum,
,E_POSITIONNAME,'+#NullToZeroCols+'
FROM
(
-- Select data before pivot
SELECT TOP 100 PERCENT ME.E_POSITIONNAME,MC.C_CANDIDATENAME,
COUNT(MC.C_CANDIDATENAME) OVER(PARTITION BY ME.E_POSITIONNAME,MC.C_CANDIDATENAME) CNT
FROM #MYELECTIONS ME
JOIN #MYCANDIDATES MC ON ME.E_POSITION_CODE=MC.C_POSITION_CODE
JOIN #MYVOTES MV ON MC.C_CANDIDATE_CODE=MV.V_CANDIDATE_CODE
AND MV.V_POSITION_CODE=MC.C_POSITION_CODE
WHERE MC.C_POSITION_CODE = ' + CAST(#MyPositionCode AS VARCHAR(30)) + '
) x
PIVOT
(
MIN(CNT)
FOR C_CANDIDATENAME IN (' + #cols + ')
) p
;'
EXEC SP_EXECUTESQL #query
Click the below link. If the result is not auto-generated, press RUN QUERY button.
Click here to view result