How to get column value into row header - sql

ID Amount Date
------------------------------
1 300 02-02-2010 00:00
2 400 02-02-2009 00:00
3 200 02-02-2011 00:00
4 300 22-02-2010 00:00
5 400 12-02-2009 00:00
6 500 22-02-2009 00:00
7 600 02-02-2006 00:00
8 700 02-07-2012 00:00
9 500 08-02-2012 00:00
10 800 09-02-2011 00:00
11 500 06-02-2010 00:00
12 600 01-02-2011 00:00
13 300 02-02-2019 00:00
Desired output:
Y1 Y2 Y3 ...........
sum(amount) sum(amount) sum(amount)
What is an approach, where Y1 is the year part of the date, such that the result column would be the following?
2006 2009 2010 2011 2012
---------------------------------
600 1300 800 1900 1200
Database system: SQL Server 2008

You need to use a dynamic PIVOT Table
DECLARE #Years nvarchar(max)
SELECT #Years =
STUFF(
(
select distinct ',[' + cast(Year([date]) as nvarchar(4)) + ']'
from YOUR_TABLE_NAME_HERE
for xml path('')
),
1,1,'')
DECLARE #SQL nvarchar(max)
SELECT #SQL = N'
select
*
from (
select
amount, year([date]) as [y]
from YOUR_TABLE_NAME_HERE
) Data
PIVOT (
sum(amount)
FOR [y]
IN (
' + #Years + '
)
) PivotTable
'
EXECUTE (#SQL)
Reference: PIVOT Docs

Related

SQL Dynamic Pivot Query With Multiple Subtotal

For below code, I able to create a dynamic pivot with subtotal.But I need to add one more subtotal column in this code . It has to be total of NUM_TO_EXIT values.As you can see picture 2, I used NUM_TO_ENTER within dynamic dates in my dynamic pivot but I could not able to merge just for the total values of NUM_TO_EXIT. I tried everything but could not able to do that. Appreciate for yor supports.I am using MSSQL 2008 R2.
DIRECTIONAL_METRIC_ID ZONE_ID START_TIME END_TIME RECEIVED_TS STATUS NUM_TO_ENTER NUM_TO_EXIT DAY_OF_WEEK_ID TIME_ID
436909 254 2016-02-06 10:00:00.000 2016-02-06 10:00:00.000 2016-02-06 10:00:00.000 1 195 195 7 300
436910 254 2016-02-07 10:00:00.000 2016-02-07 10:15:00.000 2016-02-07 10:15:00.000 1 195 195 7 300
436911 278 2016-02-01 10:00:00.000 2016-02-01 10:15:00.000 2016-02-01 10:15:00.000 1 95 95 7 300
436912 278 2016-02-02 10:00:00.000 2016-02-02 10:15:00.000 2016-02-02 10:15:00.000 1 95 95 7 300
436913 278 2016-02-03 10:00:00.000 2016-02-03 10:15:00.000 2016-02-03 10:15:00.000 1 95 95 7 300
What I need
Structe of DIRECTIONAL_METRIC TABLE
DECLARE #mydate DATETIME
SELECT #mydate = GETDATE()
IF OBJECT_ID('tempdb..#Dates') IS NOT NULL
drop table #Dates
SELECT DISTINCT CONVERT(VARCHAR,START_TIME,106) AS [Date]
INTO #Dates
FROM dbo.DIRECTIONAL_METRIC
WHERE CAST(START_TIME as DATE) >=CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(#mydate)-1),#mydate),101)
and CAST(START_TIME as DATE) < #mydate
AND DATEPART(HOUR,START_TIME) BETWEEN 9 AND 23
order by [Date]
DECLARE #cols VARCHAR(1000)
SELECT #cols = COALESCE (#cols + ',[' + [Date] +']','[' + [Date] + ']')
FROM #Dates
DECLARE #GrandTotalCol NVARCHAR (MAX)
SELECT #GrandTotalCol = COALESCE (#GrandTotalCol + 'ISNULL ([' + [Date] +'],0) + ', 'ISNULL([' + [Date]+ '],0) + ')
FROM #Dates
ORDER BY [Date]
SET #GrandTotalCol = LEFT (#GrandTotalCol, LEN (#GrandTotalCol)-1)
DECLARE #qry varchar(4000)
SET #qry =
'
DECLARE #mydate DATETIME
SELECT #mydate = GETDATE()
SELECT *, ('+ #GrandTotalCol + ')
AS [Grand Total] INTO #temp_MatchesTotal
FROM
(
SELECT ZO.CODE AS KOD,
convert(varchar, START_TIME, 106) AS [Date],
SUM(NUM_TO_ENTER) AS NUM_TO_ENTER
FROM dbo.DIRECTIONAL_METRIC AS z INNER JOIN ZONE AS ZO ON z.ZONE_ID=ZO.ZONE_ID
WHERE CAST(START_TIME as DATE) >=CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(#mydate)-1),#mydate),101)
and CAST(START_TIME as DATE) < #mydate
and DATEPART(HOUR,START_TIME) between 9 and 23
AND ZO.CODE IS NOT NULL
group by ZO.CODE,convert(varchar, START_TIME, 106)
) P
PIVOT
(
SUM(NUM_TO_ENTER)
FOR [Date] IN(' +#cols + ')
)
AS pvt
ORDER BY KOD
SELECT * FROM #temp_MatchesTotal
DROP TABLE #temp_MatchesTotal'
EXEC(#qry)
GO

Get Invoice count of sales by stores for the last three months

This is my CustomerDetails table.
CustomerID CustCodeID
25 1
65 8
35 2
112 8
45 2
975 8
364 1
48 8
69 1
97 8
33 1
11 8
93 2
10 8
21 1
65 8
74 2
53 8
This is my Fact_SalesMetrics table.
Date Sales # CustomerID
2015-03-23 00:00:00.000 42895 25
2015-03-13 00:00:00.000 53920 53
2015-03-23 00:00:00.000 44895 65
2015-03-13 00:00:00.000 43920 35
2015-03-23 00:00:00.000 48895 112
2015-03-13 00:00:00.000 47920 45
2015-03-23 00:00:00.000 46895 975
2015-03-13 00:00:00.000 45920 48
2015-03-23 00:00:00.000 40895 69
2015-03-13 00:00:00.000 40920 11
2015-03-23 00:00:00.000 41895 33
2015-03-13 00:00:00.000 49920 21
......
I wish to make output like below:
CustCodeID March 2015
1 4
2 2
8 7
Which means the customer who has codeID '1' has 4 orders on March, 2 has 2 orders and like that.
To make this happen, I queried like below and got it working:
select CustCodeID,sum(March) as 'March 2015' from (
select bb.CustCodeID, aa.March from (
(SELECT count(distinct([Sales #])) as 'March', customerid
FROM [SalesData].[dbo].[Fact_SalesMetrics] a
where date >= '2015-03-01 00:00:00.000' and date <= '2015-03-31 00:00:00.000'
and customerid in (select customerid from CustomerDetails)
group by customerid ) as aa inner join (select customerid,CustCodeID from CustomerDetails ) as bb on aa.customerid=bb.customerid
)
) as dd group by CustCodeID
Now I wish to calculate the invoices count for the last three months like below:
CustCodeID March 2015 February 2015 January 2015
1 4 ? ?
2 2 ? ?
8 7 ? ?
Can anyone help me to achieve this?
Since you have column of type DateTime, you need to convert it to Month Year format. Use DateName in Sql Server to extract the monthname and year. You should then find the count of CustomerID and GROUP BY with the new date format and CustCodeID. You should use this query as the source query for the table to pivot.
If the values of months are known in advance, you can use Static Pivot by hard-coding the column names
SELECT CustCodeID,[March 2015],[February 2015],[January 2015]
FROM
(
SELECT CD.CustCodeID,COUNT(CD.CustomerID) COUNTOfCustomerID,
DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE]) MONTHS
FROM CustomerDetails CD
JOIN Fact_SalesMetrics FS ON CD.CustomerID=FS.CustomerID
GROUP BY CD.CustCodeID,DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE])
)TAB
PIVOT
(
MIN(COUNTOfCustomerID)
FOR MONTHS IN([March 2015],[February 2015],[January 2015])
)P
SQL FIDDLE
If the numbers of columns are not known in advance, you can go for Dynamic Pivot.
For that the first step is to get the column names to be displayed after pivot from the rows. In the following query, it will select the columns for the last 3 months.
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME(MONTHS)
FROM
(
SELECT TOP 3 DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE]) MONTHS
from Fact_SalesMetrics
GROUP BY '01 ' + DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE]),
DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE])
ORDER BY CAST('01 ' + DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE]) AS DATE) DESC
) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
Now execute Pivot query using Dynamic sql
DECLARE #query NVARCHAR(MAX)
SET #query = '
SELECT * FROM
(
SELECT CD.CustCodeID,COUNT(CD.CustomerID) COUNTOfCustomerID,
DATENAME(MONTH,[DATE])+'' '' + DATENAME(YEAR,[DATE]) MONTHS
FROM CustomerDetails CD
JOIN Fact_SalesMetrics FS ON CD.CustomerID=FS.CustomerID
GROUP BY CD.CustCodeID,DATENAME(MONTH,[DATE])+'' '' + DATENAME(YEAR,[DATE])
) x
PIVOT
(
-- Specify the values to hold in pivoted column
MIN([COUNTOfCustomerID])
-- Get the column names from variable
FOR [MONTHS] IN('+#cols+')
) p
ORDER BY CustCodeID;'
EXEC SP_EXECUTESQL #query
SQL FIDDLE

data between two dates in column for each day

I have table worker
id name
----------- -------------------
5 Артур Петрович
6 Дмитрий Белов
7 Казарян Артур
and another table
id date amount id_worker
----------- ---------- ----------- -----------
27 2013-09-12 1500 5
28 2013-09-12 100 6
29 2013-09-12 500 5
30 2013-09-12 500 6
31 2013-09-14 1000 7
32 2013-09-15 100 5
33 2013-09-15 200 5
I want to write stored procedure which on input gets start and end dates
and on output I want to get this table if:
start date:2013-09-10
end date :2013-09-15
Name 2013-09-10 2013-09-11 2013-09-12 2013-09-13 2013-09-14 2013-09-15
_______________ __________ __________ __________ __________ __________ __________
Артур Петрович 0 0 2000 0 0 300
Дмитрий Белов 0 0 600 0 0 0
Казарян Артур 0 0 0 0 1000 0
The only way I konw to do this is using Dynamic SQL, IMO there is no risk of SQL Injection if the tables structures are known ahead
DECLARE #DateList VARCHAR(MAX), #DateListCoalesced VARCHAR(MAX)
SELECT #DateList = '', #DateListCoalesced = ''
;WITH DateLimits AS (
SELECT CAST('2013-9-10' AS DATE) AS dt
UNION ALL
SELECT DATEADD(dd, 1, dt)
FROM DateLimits s
WHERE DATEADD(dd, 1, dt) <= CAST('2013-9-15' AS DATE))
SELECT #DateList = #DateList + '[' + CAST(dt AS VARCHAR)+ '], ' ,
#DateListCoalesced = #DateListCoalesced + ' COALESCE( [' + CAST(dt AS VARCHAR)+ '] , 0) as [' + CAST(dt AS VARCHAR)+ '], '
FROM DateLimits
;SET #DateList = LEFT(#DateList, LEN(#DateList) - 1)
;SET #DateListCoalesced = LEFT(#DateListCoalesced, LEN(#DateListCoalesced) - 1)
DECLARE #query NVARCHAR(max)
SET #query = N'SELECT [Name], ' + #DateListCoalesced +'
FROM
(SELECT [Name], [Date], [Amount]
FROM WorkerAmount
INNER JOIN Worker ON WorkerAmount.id_worker = Worker.id
) p
PIVOT
(
Sum ([Amount] )
FOR [Date] IN ( '+ #DateList +' )
) AS pvt '
EXEC sp_executesql #Query
This answer uses a combination of few other questions
getting dates between range of dates
Pivots with dynamic columns in sql-server
replace null values in sql pivot

Pivot dynamic column

I have a table with the following values.
Date TCOUNT COUNT
02/06/2013 00:00 3500 35
02/12/2013 00:00 4000 23
02/21/2013 00:00 1000 54
02/27/2013 00:00 5000 12
where Date is dynamic col need to be pivoted.
I need to pivote the above table to get the below result
02/06/2013 00:00 02/12/2013 00:00 02/21/2013 00:00 02/27/2013 00:00
35 23 54 12
3500 4000 1000 5000
please help.
Thanks.
Based on the fact that your previous question was tagged with sql server, I am guessing that you need sql server syntax.
In order to get the result, you will need to use both the UNPIVOT and the PIVOT functions. The unpivot will take the TCount and Count columns and convert them to rows and then the PIVOT will take the dates and convert them to columns.
If you know the values ahead of time then you can hard-code the query:
select *
from
(
select date, value, col
from yourtable
unpivot
(
value
for col in (tcount, count)
) unpiv
) src
pivot
(
max(value)
for date in ([2013-02-06], [2013-02-12],
[2013-02-21], [2013-02-27])
) piv;
See SQL Fiddle with Demo
However, if you have an unknown number of dates, then you will need dynamic SQL:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(convert(varchar(10), Date, 120))
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT col, ' + #cols + ' from
(
select convert(varchar(10), Date, 120) date,
value, col
from yourtable
unpivot
(
value
for col in (tcount, count)
) unpiv
) src
pivot
(
max(value)
for date in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo
The result of both is:
| COL | 2013-02-06 | 2013-02-12 | 2013-02-21 | 2013-02-27 |
--------------------------------------------------------------
| COUNT | 35 | 23 | 54 | 12 |
| TCOUNT | 3500 | 4000 | 1000 | 5000 |

T-SQL solution for GYM trainers TimeTable and session booking [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have four tables
tblEmployees
EmployeeID Name
1 Zahiz
2 Nigon
3 Jimian
4 Ash
5 Dani
tblMembers
MemberNo FirstName
1 Saleem
2 Jamil
3 Jazi
4 funa
5 Jhon
6 Moum
RefSessions
SessionID StartTime EndTime
1 0701 0730
2 0731 0800
3 0801 0830
4 0831 0900
5 0901 0930
6 0931 1000
7 1001 1030
8 1031 1100
9 1101 1130
10 1131 1200
11 1201 1230
12 1231 1300
13 1301 1330
14 1331 1400
15 1401 1430
16 1431 1500
17 1501 1530
18 1531 1600
19 1601 1630
20 1631 1700
21 1701 1730
22 1731 1800
23 1801 1830
24 1831 1900
25 1901 1930
26 1931 2000
27 2001 2030
28 2031 2100
tblBookSession
BookingID SessionID EmployeeID MemberNo SessionDate
1 15 2 3 2012-09-30
2 16 2 3 2012-09-30
3 1 3 4 2012-10-03
4 2 3 4 2012-10-03
5 3 3 4 2012-10-03
6 4 3 4 2012-10-03
I am looking for a t-sql query resulting in said form against a specific date
Its actually booking of time slot of trainers in a gym and displaying In the form of date wise report
You will need to perform a PIVOT. There are two ways to do this with PIVOT, either a Static Pivot where you code the columns to transform or a Dynamic Pivot which determines the columns at execution.
A Static Pivot, you will need to hard-code the values:
select name,
IsNull([701-730], '') [701-730],
IsNull([731-800], '') [731-800],
IsNull([801-830], '') [801-830],
IsNull([831-900], '') [831-900]
from
(
select e.name,
cast(e.starttime as varchar(10))+'-'
+cast(e.endtime as varchar(10)) Session,
m.FirstName
from
(
select *
from tblEmployees e
cross apply RefSessions
) e
left join tblBookSession b
on e.EmployeeID = b.EmployeeID
and e.sessionid = b.sessionid
left join tblMembers m
on b.MemberNo = m.MemberNo
) x
pivot
(
max(FirstName)
for session in ([701-730], [731-800], [801-830], [831-900]) -- additional sessions here
)p
See SQL Fiddle with Demo
If you have many values to transform into columns or an unknown number of values, then you will want to use a dynamic sql version of the PIVOT:
DECLARE #cols AS NVARCHAR(MAX),
#colsPivot AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ','
+ QUOTENAME(cast(starttime as varchar(10))
+'-'+cast(endtime as varchar(10)))
from RefSessions
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsPivot = STUFF((SELECT ', IsNull('
+ QUOTENAME(cast(starttime as varchar(10))
+'-'+cast(endtime as varchar(10))) +', '''') as [' +
cast(starttime as varchar(10))
+'-'+cast(endtime as varchar(10)) + ']'
from RefSessions
group by SessionID, starttime, endtime
order by SessionID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT name, ' + #colsPivot + ' from
(
select e.name,
cast(starttime as varchar(10))+''-''
+cast(endtime as varchar(10)) Session,
m.FirstName
from
(
select *
from tblEmployees e
cross apply RefSessions
) e
left join tblBookSession b
on e.EmployeeID = b.EmployeeID
and e.sessionid = b.sessionid
left join tblMembers m
on b.MemberNo = m.MemberNo
) x
pivot
(
max(FirstName)
for Session in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo