How can I tell when a recipient in a subscription was sent the SSRS report?
I've seen similar questions but they seem to relate to which email addresses are currently subscribed to the report, rather than specific instances of when an email was sent to the recipient(s).
I've used this SQL script to find the execution log of subscriptions.
There are some example reports in my GitHub project.
USE [ReportServer];
GO
DECLARE #StartDate DATETIME = '03-MAR-2022';
DECLARE #EndDate DATETIME = '04-MAR-2022';
DECLARE #ReportFolder NVARCHAR(200) = NULL;
DECLARE #ReportName NVARCHAR(200) = NULL;
DECLARE #LogStatus NVARCHAR(200) = NULL;
DECLARE #StatusGroup NVARCHAR(200) = NULL;
DECLARE #ServiceAccount NVARCHAR(200) = 'your_service_account'; -- enter the subscription service account here
WITH
report_status
AS
(
SELECT tbl.* FROM (VALUES
( 'rrRenderingError', 'Failure')
, ( 'rsHttpRuntimeClientDisconnectionError', 'Failure')
, ( 'rsInternalError', 'Failure')
, ( 'rsInvalidDataSourceCredentialSetting', 'Failure')
, ( 'rsProcessingAborted', 'Failure')
, ( 'rsProcessingError', 'Failure')
, ( 'rsRenderingExtensionNotFound', 'Failure')
, ( 'rsReportServerDatabaseError', 'Failure')
, ( 'rsSuccess', 'Success')
) tbl ([StatusName], [StatusGroup])
)
,
report_users
AS
(
SELECT
[UserID]
, [UserName]
, [SimpleUserName] = LOWER(RIGHT([UserName], (LEN([UserName]) - CHARINDEX('\', [UserName]))))
FROM
[dbo].[Users] WITH(NOLOCK)
)
,
report_catalog
AS
(
SELECT
rpt.[ItemID]
, rpt.[CreatedById]
, rpt.[ModifiedById]
, rpt.[Type]
, rpt.[Name]
, [ReportName] = rpt.[Name]
, rpt.[Description]
, rpt.[Parameter]
, [CreationDate] = CONVERT(DATETIME, CONVERT(VARCHAR(11), rpt.[CreationDate], 13))
, [ModifiedDate] = CONVERT(DATETIME, CONVERT(VARCHAR(11), rpt.[ModifiedDate], 13))
, [ReportFolder] = SUBSTRING(rpt.[Path], 2, Len(rpt.[Path])-Len(rpt.[Name])-2)
, rpt.[Path]
, [URL_ReportFolder] = 'http://' + Host_Name() + '/Reports/Pages/Report.aspx?ItemPath=%2f' + SUBSTRING(rpt.[Path], 2, Len(rpt.[Path])-Len(rpt.[Name])-2) + '&ViewMode=List'
, [URL_Report] = 'http://' + Host_Name() + '/Reports/Pages/Report.aspx?ItemPath=%2f' + SUBSTRING(rpt.[Path], 2, Len(rpt.[Path])-Len(rpt.[Name])-2) + '%2f' + rpt.[Name]
, [ReportDefinition] = CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), rpt.[Content]))
FROM
[dbo].[Catalog] AS rpt WITH (NOLOCK)
WHERE
1=1
AND rpt.[Type] = 2
)
,
subscription_days
AS
(
SELECT tbl.* FROM (VALUES
( 'DaysOfMonth', 1, '1')
, ( 'DaysOfMonth', 2, '2')
, ( 'DaysOfMonth', 4, '3')
, ( 'DaysOfMonth', 8, '4')
, ( 'DaysOfMonth', 16, '5')
, ( 'DaysOfMonth', 32, '6')
, ( 'DaysOfMonth', 64, '7')
, ( 'DaysOfMonth', 128, '8')
, ( 'DaysOfMonth', 256, '9')
, ( 'DaysOfMonth', 512, '10')
, ( 'DaysOfMonth', 1024, '11')
, ( 'DaysOfMonth', 2048, '12')
, ( 'DaysOfMonth', 4096, '13')
, ( 'DaysOfMonth', 8192, '14')
, ( 'DaysOfMonth', 16384, '15')
, ( 'DaysOfMonth', 32768, '16')
, ( 'DaysOfMonth', 65536, '17')
, ( 'DaysOfMonth', 131072, '18')
, ( 'DaysOfMonth', 262144, '19')
, ( 'DaysOfMonth', 524288, '20')
, ( 'DaysOfMonth', 1048576, '21')
, ( 'DaysOfMonth', 2097152, '22')
, ( 'DaysOfMonth', 4194304, '23')
, ( 'DaysOfMonth', 8388608, '24')
, ( 'DaysOfMonth', 16777216, '25')
, ( 'DaysOfMonth', 33554432, '26')
, ( 'DaysOfMonth', 67108864, '27')
, ( 'DaysOfMonth', 134217728, '28')
, ( 'DaysOfMonth', 268435456, '29')
, ( 'DaysOfMonth', 536870912, '30')
, ( 'DaysOfMonth', 1073741824, '31')
, ( 'DaysOfMonth', 8193, '1st and 14th')
, ( 'DaysOfWeek', 1, 'Sun')
, ( 'DaysOfWeek', 2, 'Mon')
, ( 'DaysOfWeek', 4, 'Tues')
, ( 'DaysOfWeek', 8, 'Wed')
, ( 'DaysOfWeek', 16, 'Thurs')
, ( 'DaysOfWeek', 32, 'Fri')
, ( 'DaysOfWeek', 64, 'Sat')
, ( 'DaysOfWeek', 62, 'Mon - Fri')
, ( 'DaysOfWeek', 10, 'Mon - Wed')
, ( 'DaysOfWeek', 24, 'Wed - Thurs')
, ( 'DaysOfWeek', 120, 'Wed - Sat')
, ( 'DaysOfWeek', 126, 'Mon - Sat')
, ( 'DaysOfWeek', 127, 'Daily')
, ( 'DayOfWeek', 1, 'Sun')
, ( 'DayOfWeek', 127, 'Sun')
, ( 'DayOfWeek', 2, 'Mon')
, ( 'DayOfWeek', 10, 'Mon')
, ( 'DayOfWeek', 62, 'Mon')
, ( 'DayOfWeek', 126, 'Mon')
, ( 'DayOfWeek', 127, 'Mon')
, ( 'DayOfWeek', 4, 'Tue')
, ( 'DayOfWeek', 10, 'Tue')
, ( 'DayOfWeek', 62, 'Tue')
, ( 'DayOfWeek', 126, 'Tue')
, ( 'DayOfWeek', 127, 'Tue')
, ( 'DayOfWeek', 8, 'Wed')
, ( 'DayOfWeek', 10, 'Wed')
, ( 'DayOfWeek', 24, 'Wed')
, ( 'DayOfWeek', 62, 'Wed')
, ( 'DayOfWeek', 120, 'Wed')
, ( 'DayOfWeek', 126, 'Wed')
, ( 'DayOfWeek', 127, 'Wed')
, ( 'DayOfWeek', 16, 'Thr')
, ( 'DayOfWeek', 24, 'Thr')
, ( 'DayOfWeek', 62, 'Thr')
, ( 'DayOfWeek', 120, 'Thr')
, ( 'DayOfWeek', 126, 'Thr')
, ( 'DayOfWeek', 127, 'Thr')
, ( 'DayOfWeek', 32, 'Fri')
, ( 'DayOfWeek', 62, 'Fri')
, ( 'DayOfWeek', 120, 'Fri')
, ( 'DayOfWeek', 126, 'Fri')
, ( 'DayOfWeek', 127, 'Fri')
, ( 'DayOfWeek', 64, 'Sat')
, ( 'DayOfWeek', 120, 'Sat')
, ( 'DayOfWeek', 126, 'Sat')
, ( 'DayOfWeek', 127, 'Sat')
) tbl ([GroupName], [CodeNbr], [Label])
)
,
subscription_schedule
AS
(
SELECT
[ScheduleID]
, [SchDaySun] = Sun
, [SchDayMon] = Mon
, [SchDayTue] = Tue
, [SchDayWed] = Wed
, [SchDayThr] = Thr
, [SchDayFri] = Fri
, [SchDaySat] = Sat
, [ScheduleName]
, [ScheduleStartDate]
, [ScheduleEndDate]
, [Flags]
, [RecurrenceType]
, [State]
, [MinutesInterval]
, [DaysInterval]
, [WeeksInterval]
, [DaysOfWeek]
, [DaysOfMonth]
, [Month]
, [MonthlyWeek]
, [ScheduleDays]
FROM
(
SELECT
sc.[ScheduleID]
, sd.[CodeNbr]
, sd.[Label]
, [ScheduleName] = CASE WHEN sc.[EventType] = 'SharedSchedule' THEN sc.[name] ELSE NULL END
, [ScheduleStartDate] = sc.[StartDate]
, [ScheduleEndDate] = sc.[EndDate]
, sc.[Flags]
, sc.[RecurrenceType]
, sc.[State]
, sc.[MinutesInterval]
, sc.[DaysInterval]
, sc.[WeeksInterval]
, sc.[DaysOfWeek]
, sc.[DaysOfMonth]
, sc.[Month]
, sc.[MonthlyWeek]
, [ScheduleDays] =
CASE
WHEN sc.[DaysOfMonth] IS NOT NULL THEN COALESCE(dom.[Label], '(' + CAST(sc.[DaysOfMonth] AS VARCHAR(20)) + ') NOT CODED')
WHEN sc.[DaysOfWeek] IS NOT NULL THEN COALESCE(dow.[Label], '(' + CAST(sc.[DaysOfWeek] AS VARCHAR(20)) + ') NOT CODED')
END
FROM
[dbo].[Schedule] sc WITH (NOLOCK)
LEFT JOIN subscription_days sd ON sc.[DaysOfWeek] = sd.[CodeNbr] AND sd.[GroupName] = 'DayOfWeek'
LEFT JOIN subscription_days AS dom ON sc.[DaysOfMonth] = dom.[CodeNbr] AND dom.[GroupName] = 'DaysOfMonth'
LEFT JOIN subscription_days AS dow ON sc.[DaysOfWeek] = dow.[CodeNbr] AND dow.[GroupName] = 'DaysOfWeek'
) sch
PIVOT
(
COUNT(sch.[Label])
FOR sch.[Label]
IN ([Sun], [Mon], [Tue], [Wed], [Thr], [Fri], [Sat])
) AS pvt
)
,
report_subscription
AS
(
SELECT
sub.[SubscriptionID]
, sub.[Report_OID]
, [SubscriptionDescription] = sub.[Description]
, sub.[ExtensionSettings]
, sub.[EventType]
, sub.[OwnerID]
, sub.[ModifiedByID]
, sub.[ModifiedDate]
, [RunTime] = CONVERT(VARCHAR(5), sub.[LastRunTime], 8)
, [LastRunDate] = CONVERT(VARCHAR(11), sub.[LastRunTime], 13)
, [LastRunTime] = CAST(CONVERT(CHAR(16), sub.[LastRunTime], 113) AS DATETIME)
, sub.[DeliveryExtension]
, sub.[MatchData]
, [SubscriptionLastStatus] = sub.[LastStatus]
, [StatusFail] = CASE WHEN sub.[LastStatus] LIKE '%Mail sent%' THEN 'N' ELSE 'Y' END
, [EmailSubject] = CASE CHARINDEX('<Name>SUBJECT</Name><Value>', sub.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(sub.ExtensionSettings, LEN('<Name>SUBJECT</Name><Value>') + CHARINDEX('<Name>SUBJECT</Name><Value>', sub.ExtensionSettings), CHARINDEX('</Value>', sub.ExtensionSettings, CHARINDEX('<Name>SUBJECT</Name><Value>', sub.ExtensionSettings) + 1) - (LEN('<Name>SUBJECT</Name><Value>') + CHARINDEX('<Name>SUBJECT</Name><Value>', sub.ExtensionSettings))) END
, [EmailTo] = SUBSTRING(sub.ExtensionSettings, LEN('<Name>TO</Name><Value>') + CHARINDEX('<Name>TO</Name><Value>', sub.ExtensionSettings), CHARINDEX('</Value>', sub.ExtensionSettings, CHARINDEX('<Name>TO</Name><Value>', sub.ExtensionSettings) + 1) - (LEN('<Name>TO</Name><Value>') + CHARINDEX('<Name>TO</Name><Value>', sub.ExtensionSettings)))
, [EmailCc] = CASE CHARINDEX('<Name>CC</Name><Value>', sub.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(sub.ExtensionSettings, LEN('<Name>CC</Name><Value>') + CHARINDEX('<Name>CC</Name><Value>', sub.ExtensionSettings), CHARINDEX('</Value>', sub.ExtensionSettings, CHARINDEX('<Name>CC</Name><Value>', sub.ExtensionSettings) + 1) - (LEN('<Name>CC</Name><Value>') + CHARINDEX('<Name>CC</Name><Value>', sub.ExtensionSettings))) END
, [EmailBcc] = CASE CHARINDEX('<Name>BCC</Name><Value>', sub.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(sub.ExtensionSettings, LEN('<Name>BCC</Name><Value>') + CHARINDEX('<Name>BCC</Name><Value>', sub.ExtensionSettings), CHARINDEX('</Value>', sub.ExtensionSettings, CHARINDEX('<Name>BCC</Name><Value>', sub.ExtensionSettings) + 1) - (LEN('<Name>BCC</Name><Value>') + CHARINDEX('<Name>BCC</Name><Value>', sub.ExtensionSettings))) END
, [EmailComment] = CASE CHARINDEX('<Name>Comment</Name><Value>', sub.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(sub.ExtensionSettings, LEN('<Name>Comment</Name><Value>') + CHARINDEX('<Name>Comment</Name><Value>', sub.ExtensionSettings), CHARINDEX('</Value>', sub.ExtensionSettings, CHARINDEX('<Name>Comment</Name><Value>', sub.ExtensionSettings) + 1) - (LEN('<Name>Comment</Name><Value>') + CHARINDEX('<Name>Comment</Name><Value>', sub.ExtensionSettings))) END
, [EmailIncludeLink] = CASE CHARINDEX('<Name>IncludeLink</Name><Value>', sub.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(sub.ExtensionSettings, LEN('<Name>IncludeLink</Name><Value>') + CHARINDEX('<Name>IncludeLink</Name><Value>', sub.ExtensionSettings), CHARINDEX('</Value>', sub.ExtensionSettings, CHARINDEX('<Name>IncludeLink</Name><Value>', sub.ExtensionSettings) + 1) - (LEN('<Name>IncludeLink</Name><Value>') + CHARINDEX('<Name>IncludeLink</Name><Value>', sub.ExtensionSettings))) END
, [EmailRenderFormat] = CASE CHARINDEX('<Name>RenderFormat</Name><Value>', sub.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(sub.ExtensionSettings, LEN('<Name>RenderFormat</Name><Value>') + CHARINDEX('<Name>RenderFormat</Name><Value>', sub.ExtensionSettings), CHARINDEX('</Value>', sub.ExtensionSettings, CHARINDEX('<Name>RenderFormat</Name><Value>', sub.ExtensionSettings) + 1) - (LEN('<Name>RenderFormat</Name><Value>') + CHARINDEX('<Name>RenderFormat</Name><Value>', sub.ExtensionSettings))) END
, [EmailPriority] = CASE CHARINDEX('<Name>Priority</Name><Value>', sub.ExtensionSettings) WHEN 0 THEN '' ELSE SUBSTRING(sub.ExtensionSettings, LEN('<Name>Priority</Name><Value>') + CHARINDEX('<Name>Priority</Name><Value>', sub.ExtensionSettings), CHARINDEX('</Value>', sub.ExtensionSettings, CHARINDEX('<Name>Priority</Name><Value>', sub.ExtensionSettings) + 1) - (LEN('<Name>Priority</Name><Value>') + CHARINDEX('<Name>Priority</Name><Value>', sub.ExtensionSettings))) END
, sch.[MinutesInterval]
, sch.[DaysInterval]
, sch.[WeeksInterval]
, sch.[DaysOfWeek]
, sch.[DaysOfMonth]
, sch.[Month]
, sch.[MonthlyWeek]
, sch.[ScheduleName]
, sch.[ScheduleDays]
, sch.[SchDaySun]
, sch.[SchDayMon]
, sch.[SchDayTue]
, sch.[SchDayWed]
, sch.[SchDayThr]
, sch.[SchDayFri]
, sch.[SchDaySat]
, sch.[ScheduleStartDate]
, sch.[ScheduleEndDate]
, sch.[Flags]
, sch.[RecurrenceType]
, sch.[State]
, sub.[LastStatus]
, rs.[ScheduleID]
FROM
[dbo].[Subscriptions] AS sub WITH (NOLOCK)
LEFT JOIN [dbo].[Notifications] AS n WITH (NOLOCK) ON n.[SubscriptionID] = sub.[SubscriptionID] AND sub.[Report_OID] = n.[ReportID]
LEFT JOIN [dbo].[ReportSchedule] AS rs WITH (NOLOCK) ON sub.[SubscriptionID] = rs.[SubscriptionID]
LEFT JOIN subscription_schedule AS sch ON rs.[ScheduleID] = sch.[ScheduleID]
)
SELECT
rpt.[Path]
, rpt.[ReportFolder]
, rpt.[Name]
, rpt.[URL_ReportFolder]
, rpt.[URL_Report]
, [URL_Report_Filtered] = rpt.URL_Report + '&rs:Command=Render&' + CONVERT(VARCHAR(2000), el.[Parameters])
, [UserName] = usr.[SimpleUserName]
, el.[Status]
, el.[TimeStart]
, el.[RowCount]
, el.[ByteCount]
, el.[Format]
, [Parameters] =
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(CONVERT(NVARCHAR(MAX), el.[Parameters])
, '%20', ' ')
, '%2F', '-')
, '%3C', '<')
, '%3E', '>')
, '%3A', ':')
, [TotalSeconds] = CONVERT(CHAR(8),DATEADD(ms, (el.[TimeDataRetrieval] + el.[TimeProcessing] + el.[TimeRendering]), 0), 108)
, [TimeDataRetrieval] = CONVERT(CHAR(8),DATEADD(ms, el.[TimeDataRetrieval], 0), 108)
, [TimeProcessing] = CONVERT(CHAR(8),DATEADD(ms, el.[TimeProcessing], 0), 108)
, [TimeRendering] = CONVERT(CHAR(8),DATEADD(ms, el.[TimeRendering], 0), 108)
, [SubscriptionOwner] = usc.[SimpleUserName]
, [SubscriptionModifiedBy] = usm.[SimpleUserName]
, [SubscriptionModifiedDate] = sub.[ModifiedDate]
, sub.[SubscriptionID]
, sub.[SubscriptionDescription]
, sub.[ExtensionSettings]
, sub.[EventType]
, sub.[EmailSubject]
, sub.[EmailTo]
, sub.[EmailCc]
, sub.[EmailBcc]
, sub.[EmailComment]
, sub.[EmailIncludeLink]
, sub.[EmailRenderFormat]
, sub.[EmailPriority]
, sub.[DeliveryExtension]
, [DeliveryExtensionImage] =
CASE
WHEN sub.[DeliveryExtension] = 'Report Server Email' THEN 'email'
WHEN sub.[DeliveryExtension] = 'Report Server FileShare' THEN 'folder'
ELSE sub.[DeliveryExtension]
END
, sub.[SubscriptionLastStatus]
, sub.[StatusFail]
, sub.[MatchData]
, sub.[RunTime]
, sub.[LastRunDate]
, sub.[LastRunTime]
, sub.[MinutesInterval]
, sub.[DaysInterval]
, sub.[WeeksInterval]
, sub.[DaysOfWeek]
, sub.[DaysOfMonth]
, sub.[Month]
, sub.[MonthlyWeek]
, sub.[ScheduleName]
, sub.[ScheduleDays]
, sub.[SchDaySun]
, sub.[SchDayMon]
, sub.[SchDayTue]
, sub.[SchDayWed]
, sub.[SchDayThr]
, sub.[SchDayFri]
, sub.[SchDaySat]
, sub.[ScheduleStartDate]
, sub.[ScheduleEndDate]
, sub.[Flags]
, sub.[RecurrenceType]
, sub.[State]
, [EventStatus] = el.[Status]
, [EventDateTime] = el.[TimeEnd]
, sub.[LastStatus]
, sub.[ScheduleID]
FROM
report_catalog AS rpt
INNER JOIN report_subscription AS sub ON sub.[Report_OID] = rpt.[ItemID]
LEFT JOIN [dbo].[ExecutionLog] AS el WITH (NOLOCK) ON el.[ReportID] = rpt.[ItemID]
LEFT JOIN report_status AS rs ON el.[Status] = rs.[StatusName]
LEFT JOIN report_users AS usr ON el.[UserName] = usr.[UserName]
LEFT JOIN report_users AS usc ON sub.[OwnerID] = usc.[UserID]
LEFT JOIN report_users AS usm ON sub.[ModifiedByID] = usm.[UserID]
WHERE
1=1
AND (#StartDate IS NULL OR el.[TimeStart] >= #StartDate)
AND (#EndDate IS NULL OR el.[TimeStart] <= #EndDate)
AND (#ReportFolder IS NULL OR rpt.[ReportFolder] = #ReportFolder)
AND (#ReportName IS NULL OR rpt.[ReportName] = #ReportName)
AND (#LogStatus IS NULL OR el.[Status] = #LogStatus)
AND (#StatusGroup IS NULL OR rs.[StatusGroup] = #StatusGroup)
AND (#ServiceAccount IS NULL OR usr.[SimpleUserName] = #ServiceAccount)
ORDER BY
rpt.[Path]
, el.[TimeStart] DESC
Software used: SQL Server 2014 Management Studio to query a standard 64-bit SQL Server.
I'm trying to create a query that generates a set of patient assessment results across multiple patients / assessments, and to put the results of each assessment on one row. This would suggest the use of pivoting of some sort.
Each assessment consists of a number of tests, each of which has a type, a name and a score. It is possible that we may want to add more tests to an assessment at some point, which would suggest the use of dynamic pivots.
At the moment, my query essentially looks like this:
SELECT TOP 20000
P.PatientId,
P.LastName,
P.FirstName,
FORMAT(P.DateOfBirth, 'dd/MM/yyyy') as 'DateOfBirth',
FORMAT(A.TreatmentDate, 'dd/MM/yyyy') as 'AssmentDate',
A.TestType,
A.TestName,
A.TestScore
FROM
Patient P
INNER JOIN
Assessment A ON (A.PatientSerialNumber = P.PatientSerialNumber)
INNER JOIN
AssessmentHeader AH ON (AH.AssessmentSerialNumber = A.AssessmentSerialNumber
AND AH.PatientSerialNumber = P.PatientSerialNumber)
WHERE
A.ValidEntryIndicator = 'Y'
AND AH.ValidEntryIndicator = 'Y'
ORDER BY
P.PatientId, T.TreatmentDate
My results essentially look like this (there are actually a lot more test types and names than shown here - these are just for illustration):
PatientId
LastName
FirstName
DateOfBirth
AssmentDate
TestType
TestName
TestScore
AB1234
PATIENT
Test
1/1/2000
1/1/2020
Renal
Urgency
0
AB1234
PATIENT
Test
1/1/2000
1/1/2020
Renal
Retention
1
AB1234
PATIENT
Test
1/1/2000
1/1/2020
GI
Proctitis
2
AB1234
PATIENT
Test
1/1/2000
1/1/2020
GI
Diarrhea
3
AB1234
PATIENT
Test
1/1/2000
6/6/2021
Renal
Urgency
1
AB1234
PATIENT
Test
1/1/2000
6/6/2021
Renal
Retention
0
AB1234
PATIENT
Test
1/1/2000
6/6/2021
GI
Proctitis
1
AB1234
PATIENT
Test
1/1/2000
6/6/2021
GI
Diarrhea
2
YZ6789
PATIENT2
Test2
1/1/1999
7/7/2020
Renal
Urgency
2
YZ6789
PATIENT2
Test2
1/1/1999
7/7/2020
Renal
Retention
5
YZ6789
PATIENT2
Test2
1/1/1999
7/7/2020
GI
Proctitis
3
YZ6789
PATIENT2
Test2
1/1/1999
7/7/2020
GI
Diarrhea
1
YZ6789
PATIENT2
Test2
1/1/1999
6/7/2021
Renal
Urgency
2
YZ6789
PATIENT2
Test2
1/1/1999
6/7/2021
Renal
Retention
9
YZ6789
PATIENT2
Test2
1/1/1999
6/7/2021
GI
Proctitis
4
YZ6789
PATIENT2
Test2
1/1/1999
6/7/2021
GI
Diarrhea
5
What I would like is this:
PatientId
LastName
FirstName
DateOfBirth
AssmentDate
Renal-Urgency
Renal-Retention
GI-Proctitis
GI-Diarrhea
AB1234
PATIENT
Test
1/1/2000
1/1/2020
0
1
2
3
AB1234
PATIENT
Test
1/1/2000
6/6/2021
1
0
1
2
YZ6789
PATIENT2
Test2
1/1/1999
7/7/2020
2
5
3
1
YZ6789
PATIENT2
Test2
1/1/1999
6/7/2021
2
9
4
5
I've tried to follow various online resources and SO question/answers (this one looked the most promising), but I just can't seem to get the methods shown in these to work with my query (frustratingly)
Can anyone help me out?
So you can use the technique shown at the linked answer, you just need to extend it to handle multiple key-columns and multiple pivot-source columns:
CREATE TABLE #Table (
-- key columns
PatientId Varchar(8),
LastName VarChar(32),
FirstName Varchar(32),
DateOfBirth DateTime,
AssmentDate DateTime,
-- pivot-source columns
TestType Varchar(20),
TestName Varchar(20),
-- value column
TestScore INT
)
go
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '1/1/2020', 'Renal', 'Urgency', '0');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '1/1/2020', 'Renal', 'Retention', '1');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '1/1/2020', 'GI', 'Proctitis', '2');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '1/1/2020', 'GI', 'Diarrhea', '3');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '6/6/2021', 'Renal', 'Urgency', '1');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '6/6/2021', 'Renal', 'Retention', '0');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '6/6/2021', 'GI', 'Proctitis', '1');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '6/6/2021', 'GI', 'Diarrhea', '2');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '7/7/2020', 'Renal', 'Urgency', '2');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '7/7/2020', 'Renal', 'Retention', '5');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2 ', '1/1/1999', '7/7/2020', 'GI', 'Proctitis', '3');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '7/7/2020', 'GI', 'Diarrhea', '1');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '6/7/2021', 'Renal', 'Urgency', '2');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '6/7/2021', 'Renal ', 'Retention', '9');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '6/7/2021', 'GI', 'Proctitis', '4');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '6/7/2021', 'GI', 'Diarrhea', '5');
go
DECLARE #cols NVARCHAR(2000)
DECLARE #query NVARCHAR(4000)
SELECT #cols = STUFF(( SELECT DISTINCT TOP 100 PERCENT
'],[' + t.TestType + '-' + t.TestName
FROM #Table AS t
FOR XML PATH('')
), 1, 2, '') + ']'
SELECT #cols
SET #query = N'SELECT PatientId, LastName, FirstName, DateOfBirth, AssmentDate, '
+ #cols
+' FROM
(SELECT PatientId, LastName, FirstName, DateOfBirth, AssmentDate, '
+' TestType + ''-'' + TestName AS ColName, TestScore FROM #Table AS t1) p
PIVOT (MAX([TestScore]) FOR ColName IN ( '+ #cols +' ))
AS pvt;'
PRINT(#query)
EXECUTE(#query)
DROP TABLE #Table
GO
In your case, you would use the query you have in your question to load #Table. I had to guess about the length of the Varchar(..) columns, so you will need to check and correct them.
Pivot is based on column values so the answer depends on what values are there in the columns.
CREATE TABLE #Table (
-- key columns
PatientId Varchar(8),
LastName VarChar(32),
FirstName Varchar(32),
DateOfBirth DateTime,
AssesmentDate DateTime,
-- pivot-source columns
TestType Varchar(20),
TestName Varchar(20),
-- value column
TestScore INT
)
go
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '1/1/2020', 'Renal', 'Urgency', '0');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '1/1/2020', 'Renal', 'Retention', '1');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '1/1/2020', 'GI', 'Proctitis', '2');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '1/1/2020', 'GI', 'Diarrhea', '3');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '6/6/2021', 'Renal', 'Urgency', '1');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '6/6/2021', 'Renal', 'Retention', '0');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '6/6/2021', 'GI', 'Proctitis', '1');
INSERT INTO #Table Values('AB1234', 'PATIENT', 'Test', '1/1/2000', '6/6/2021', 'GI', 'Diarrhea', '2');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '7/7/2020', 'Renal', 'Urgency', '2');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '7/7/2020', 'Renal', 'Retention', '5');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2 ', '1/1/1999', '7/7/2020', 'GI', 'Proctitis', '3');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '7/7/2020', 'GI', 'Diarrhea', '1');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '6/7/2021', 'Renal', 'Urgency', '2');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '6/7/2021', 'Renal', 'Retention', '9');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '6/7/2021', 'GI', 'Proctitis', '4');
INSERT INTO #Table Values('YZ6789', 'PATIENT2', 'Test2', '1/1/1999', '6/7/2021', 'GI', 'Diarrhea', '5');
go
--select * from #Table
DECLARE #SQL AS VARCHAR(MAX)
, #cols_ AS VARCHAR(MAX)
--Making the column list dynamically
SELECT #cols_ = STUFF((SELECT DISTINCT ', '+QUOTENAME( C.TestType +'-'+C.TestName)
FROM #Table C
FOR XML PATH('')), 1, 1, '')
--preparing PIVOT query dynamically.
select #cols_ --View the columns
SET #SQL = ' SELECT
pivoted.PatientId
,pivoted.FirstName
,pivoted.LastName
,pivoted.DateOfBirth
,pivoted.AssesmentDate
,'+#cols_+'
FROM
(
SELECT PatientId ,
LastName ,
FirstName,
DateOfBirth,
AssesmentDate,
TestType+''-''+ TestName as [PivotedCol],
TestScore
FROM #Table
) AS cp
PIVOT
(
MAX([CP].[TestScore])
FOR [CP].[PivotedCol] IN (' + #cols_ + ')
) AS pivoted; ' ;
PRINT(#SQL)
EXECUTE(#SQL)
DROP TABLE #Table
i have a query but i don't know why it is bad.
The error is: SQL (4104): Invalid column name 'CUSTOMDATA2' The multi-part identifier "PCO.QUALIFICATIONCODE.code" could not be bound, but i don't uderstand where and why it is bad.
I am very lost with this query :/, some guru of querys can i help me ?.
Edited query for dont hurt people.
Thank you in advance.
SELECT PCO_QUALIFICATIONCODE.CODE,
CASE
WHEN (ActividadesActivas.[CUSTOMDATA2] IS NULL)
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE BIS
WHERE SERVICEID = 1
AND BIS.CODE = SUBSTRING(CAST(PCO_QUALIFICATIONCODE.CODE AS VARCHAR), 1, 3)
)
ELSE ActividadesActivas.[CUSTOMDATA2]
END CUSTOMDATA2,
CASE
WHEN (ActividadesActivas.[CUSTOMDATA3] IS NULL)
THEN
CASE
WHEN (SUBSTRING(CAST(CODE AS VARCHAR), 5, 1) <> '')
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE BIS
WHERE SERVICEID = 1
AND BIS.CODE = SUBSTRING(CAST(PCO_QUALIFICATIONCODE.CODE AS VARCHAR), 1, 5)
)
WHEN (SUBSTRING(CAST(CODE AS VARCHAR), 4, 1) <> '')
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE BIS
WHERE SERVICEID = 1
AND BIS.CODE = SUBSTRING(CAST(PCO_QUALIFICATIONCODE.CODE AS VARCHAR), 1, 4)
)
WHEN ActividadesActivas.[CUSTOMDATA3] IS NULL
OR ActividadesActivas.[CUSTOMDATA3] = 'NULL'
THEN ''
ELSE ActividadesActivas.[CUSTOMDATA3]
END
ELSE ActividadesActivas.[CUSTOMDATA3]
END CUSTOMDATA3,
Totales.TOTAL
FROM [SQLPR1].[PREP].PCO_QUALIFICATIONCODE
LEFT JOIN
(SELECT [QCODE],
CASE
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) = '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) = '') )
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3)
)
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) <> '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) = '') )
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3)
)
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) <> '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) <> '') )
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3)
)
END CUSTOMDATA2,
CASE
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) = '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) = '') )
THEN
CASE
WHEN CUSTOMDATA3 IS NULL
OR CUSTOMDATA3 = 'NULL'
THEN ''
ELSE CUSTOMDATA3
END
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) <> '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) = '') )
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 4)
)
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) <> '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) <> '') )
THEN
CASE
WHEN (SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 4)) IS NOT NULL
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 4)
) + ' / ' +
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 5)
)
ELSE
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 5)
)
END
ELSE ''
END CUSTOMDATA3
FROM [SQLPR1].[PREP].[PCO_INBOUNDLOG]
WHERE SERVICEID = 1
AND QCODE > 9
GROUP BY QCODE,
CUSTOMDATA2,
CUSTOMDATA3
) ActividadesActivas
ON PCO_QUALIFICATIONCODE.CODE = ActividadesActivas.QCODE
LEFT JOIN
(SELECT [QCODE],
CASE
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) = '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) = '') )
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3)
)
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) <> '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) = '') )
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3)
)
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) <> '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) <> '') )
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3)
)
END CUSTOMDATA2,
CASE
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) = '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) = '') )
THEN
CASE
WHEN CUSTOMDATA3 IS NULL
OR CUSTOMDATA3 = 'NULL'
THEN ''
ELSE CUSTOMDATA3
END
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) <> '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) = '') )
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 4)
)
WHEN ((SUBSTRING(CAST(QCODE AS VARCHAR), 1, 3) IS NOT NULL)
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 4, 1) <> '')
AND (SUBSTRING(CAST(QCODE AS VARCHAR), 5, 1) <> '') )
THEN
CASE
WHEN (SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 4)) IS NOT NULL
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 4)
) + ' / ' +
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 5)
)
ELSE
(SELECT Description
FROM PCO_QUALIFICATIONCODE
WHERE SERVICEID = 1
AND CODE = SUBSTRING(CAST(QCODE AS VARCHAR), 1, 5)
)
END
ELSE ''
END CUSTOMDATA3,
COUNT(*) TOTAL
FROM [SQLPR1].[PREP].[PCO_INBOUNDLOG]
WHERE [SERVICEID] = 1
AND RDATE BETWEEN '2017/02/01 00:00:00' AND '2018/02/20 23:59:59'
GROUP BY QCODE,
CUSTOMDATA2,
CUSTOMDATA3
) Totales
ON ActividadesActivas.QCODE = Totales.QCODE
AND ActividadesActivas.CUSTOMDATA2 = Totales.CUSTOMDATA2
AND ActividadesActivas.CUSTOMDATA3 = Totales.CUSTOMDATA3
WHERE SERVICEID = 1
AND PCO_QUALIFICATIONCODE.CODE NOT IN (102,103,104,105,106,107,113)
GROUP BY PCO_QUALIFICATIONCODE.CODE,
ActividadesActivas.CUSTOMDATA2,
ActividadesActivas.CUSTOMDATA3,
Totales.TOTAL
ORDER BY CAST(PCO_QUALIFICATIONCODE.CODE AS VARCHAR),
CUSTOMDATA2
Your problem here is in the group by.
You are masking your field "ActividadesActivas.[CUSTOMDATA2]" with "CUSTOMDATA2"
CASE
WHEN (ActividadesActivas.[CUSTOMDATA2] IS NULL)
THEN
(SELECT Description
FROM PCO_QUALIFICATIONCODE BIS
WHERE SERVICEID = 1
AND BIS.CODE = SUBSTRING(CAST(PCO_QUALIFICATIONCODE.CODE AS VARCHAR), 1, 3)
)
ELSE ActividadesActivas.[CUSTOMDATA2]
END CUSTOMDATA2,
so, in the group by, you can only use "CUSTOMDATA2" and not "ActividadesActivas.[CUSTOMDATA2]"
GROUP BY PCO_QUALIFICATIONCODE.CODE,
ActividadesActivas.CUSTOMDATA2,
ActividadesActivas.CUSTOMDATA3,
Totales.TOTAL
PS: same rule should apply to remaining fields.
EDIT: I'm not sure if that is the only issue with your query, but that is the reason for your issue "Invalid column name 'CUSTOMDATA2'"