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

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

Related

SQL Server - SUM and comma-separated values using GROUP BY clause

I have 2 tables:
NDEvent:
EventId EndTime
33 2020-10-23 15:00:00.000
33 2020-10-23 15:00:00.000
35 2020-10-21 03:30:00.000
35 2020-10-24 15:00:00.000
35 2020-10-25 15:00:00.000
34 2020-10-23 15:00:00.000
EventAppointment:
Id DocId EventId Amount
1 7647 34 10.00
2 7647 34 10.00
3 28531 33 20.00
4 7647 35 20.00
5 7647 35 100.00
6 7647 35 200.00
And I want result to be like this:
DocId EventId Amount Id
7647 34 20.00 1,2
28531 33 20.00 3
7647 35 320.00 4,5,6
What I have tried is:
select e.Amount,e.DoctorId,e.EventId,
Id= STUFF(
(SELECT DISTINCT ',' + CAST(e.Id as nvarchar(max))
from NDEvent nd
inner join EventAppointment e on nd.Id = e.EventId
where
GETDATE() > nd.EndTime
GROUP BY
e.Amount,e.DoctorId,e.EventId,e.Id
FOR XML PATH(''))
, 1, 1, ''
)
from NDEvent nd
inner join EventAppointment e on nd.Id = e.EventId
where
GETDATE() > nd.EndTime
GROUP BY
e.Amount,e.DoctorId,e.EventId
But it is not giving expected result.
Could anyone help with this query? Or point me to a right direction? Thank you.
It doesn't look like yo need to NDEvent table here at all (though I include it in the sample data). Just SUM and STRING_AGG against EventAppointment:
USE Sandbox
GO
WITH NDEvent AS(
SELECT *
FROM (VALUES(33,CONVERT(datetime,'2020-10-23T15:00:00.000')),
(33,CONVERT(datetime,'2020-10-23T15:00:00.000')),
(35,CONVERT(datetime,'2020-10-21T03:30:00.000')),
(35,CONVERT(datetime,'2020-10-24T15:00:00.000')),
(35,CONVERT(datetime,'2020-10-25T15:00:00.000')),
(34,CONVERT(datetime,'2020-10-23T15:00:00.000')))V(EventID,EndTime)),
EventAppointment AS(
SELECT *
FROM (VALUES(1,7647 ,34,10.00),
(2,7647 ,34,10.00),
(3,28531,33,20.00),
(4,7647 ,35,20.00),
(5,7647 ,35,100.00),
(6,7647 ,35,200.00))V(Id,DocId, EventID, Amount))
SELECT DocID,
EventID,
SUM(Amount) AS Amount,
STRING_AGG(Id,',') WITHIN GROUP (ORDER BY Id) AS IDs
FROM EventAppointment EA
GROUP BY DocId,
EventID;
Can be used in other data.
WITH Table1 AS(
SELECT EventId FROM NDEvent
GROUP BY EventId
),
Table2 AS(
SELECT e.DocId,e.EventId,e.Amount,
STUFF((
SELECT ',' + CAST(ee.Id as nvarchar)
FROM EventAppointment ee
where ee.EventId = e.EventId
GROUP BY ee.EventId,ee.Id
FOR XML PATH('')), 1, 1, '') AS Id
FROM Table1 t
LEFT OUTER JOIN EventAppointment e ON t.EventId = e.EventId
)
SELECT DocId,EventId,SUM(Amount) AS Amount,Id FROM Table2
GROUP BY DocId,EventId,Id

SQL metric rows to date columns-

Suppose I have the following table:
Client ContainerID Year Month NumberOfViews
bar 116025 2019 1 2
dandy 2753 2020 1 3
dandy 2753 2020 2 2
dandy 4247 2020 1 1
demo 20037 2019 1 1
I want it to transform to the following table:
Client ContainerID Jan-2019 Jan-2020 Feb-2020
bar 116025 2 0 0
dandy 2753 0 3 2
dandy 4247 0 1 0
demo 20037 1 0 0
meaning: year + month cell rows turns into columns and the value for 'NumberOfViews' goes to the right date column.
There you go.
Replace your table name:
WITH cte AS(
SELECT Client
,ContainerId
,NumberOfViews
,FORMAT(CAST(CAST([Year] AS CHAR(4)) + '-' + CAST([Month] AS CHAR(2)) + '-01' AS DATE), 'MMM-yyyy') AS [DateCol]
FROM dbo.Test)
SELECT Client
,ContainerId
,ISNULL([Jan-2019], 0) AS [Jan-2019]
,ISNULL([Jan-2020], 0) AS [Jan-2020]
,ISNULL([Feb-2020], 0) AS [Feb-2020]
FROM cte
PIVOT
(
SUM(NumberOfViews)
FOR DateCol IN ([Jan-2019], [Jan-2020], [Feb-2020])
) AS PivotTable;
I think you need a Dynamic PIVOT as the month-year is not static. Please try this below logic-
Please use your original table name where ever you found "your_table" in the script.
DECLARE #cols AS NVARCHAR(MAX),
#sqlCommand AS NVARCHAR(MAX);
SELECT #cols =
STUFF((SELECT ( '],[' + A.YM)
FROM
(
SELECT
CASE Month
WHEN 1 THEN 'Jan-' WHEN 2 THEN 'Feb-' WHEN 3 THEN 'Mar-'
WHEN 4 THEN 'Apr-' WHEN 5 THEN 'May-' WHEN 6 THEN 'Hun-'
WHEN 7 THEN 'Jul-' WHEN 8 THEN 'Aug-' WHEN 9 THEN 'Sep-'
WHEN 10 THEN 'Oct-' WHEN 11 THEN 'Nov-' WHEN 12 THEN 'Dec-'
END
+ CAST(Year AS VARCHAR) YM
FROM your_table
) A
ORDER BY A.YM
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')+']'
FROM your_table
SET #sqlCommand=
N'SELECT Client,ContainerID,'+SUBSTRING(#cols,2,LEN(#cols))+'
FROM
(
SELECT Client,ContainerID,YM,NumberOfViews
FROM
(
SELECT Client,ContainerID,NumberOfViews,
CASE Month
WHEN 1 THEN ''Jan-'' WHEN 2 THEN ''Feb-'' WHEN 3 THEN ''Mar-''
WHEN 4 THEN ''Apr-'' WHEN 5 THEN ''May-'' WHEN 6 THEN ''Hun-''
WHEN 7 THEN ''Jul-'' WHEN 8 THEN ''Aug-'' WHEN 9 THEN ''Sep-''
WHEN 10 THEN ''Oct-'' WHEN 11 THEN ''Nov-'' WHEN 12 THEN ''Dec-''
END
+ CAST(Year AS VARCHAR) YM
FROM your_table
)A
) AS P
PIVOT
(
SUM(NumberOfViews)
FOR YM IN('+SUBSTRING(#cols,2,LEN(#cols))+')
) PVT'
--PRINT #sqlCommand
EXEC (#sqlCommand)

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

How to get column value into row header

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