I am having an issue with a dynamic query to pivot on an unknown number of columns in MS SQL server 2014. I've based my query on the article SQL Server 2005 Pivot on Unknown Number of Columns and other similar articles. However, I am having two issues that I can't decipher.
When executing the dynamic SQL, I get this error:
The name 'SELECT Code, LastName, FirstName, [03-30-2021],[06-30-2021],[08-00-2021],[10-30-2021],[12-30-2021],[17-30-2021],[18-30-2021],[19-30-2021],[20-30-2021],[21-30-2021],[22-30-2021],[24-30-2021],[25-30-2021],[26-30-2021],[29-30-2021] FROM (
SELECT i.Code, aa.LastName, aa.FirstName, FORMAT(StartDate, 'dd-mm-yyyy') AS StartDate, FORMAT(s.SignOut-s.SignIn, 'hh:mm') AS AttendanceTime
FROM ActualSession AS a INNER JOIN ActualAttendee aa ON( a.id = aa.ActualSessionId)
INNER JOIN Attendee att ON (att.Id = aa.AttendeeId)
LEFT JOIN SignIn s ON (a.Id = s.ActualSessionId) LEFT JOIN Identification i ON (i.AttendeeId = aa.AttendeeId
AND i.Id' is not a valid identifier.
However, if I copy and paste the query into a separate window in SQL Server Management Studio, it runs... I can't see what is wrong, except that the error message is only returning the first xxx characters of the query... Any suggestions as to what I have done wrong would be appreciated. Is it the joins, or the way I've selected columns?
BUT... that takes me to the second issue. When I do run the copied query text separately, it works but it is showing the same values (time in hours/minutes) for all users, rather than the user-specific values (though users who did not sign in are correctly coming up NULL). The pivot seems to need a min/max/other aggregate, but where it should be keeping it to each user (according to what I can see, by some SQL voodoo), it's not... The column names also appear to be coming up in US date format, even though I've specified the format as Australian (dd-mm-yyyy). If anyone knows how to correct these issues, that would also be appreciated.
Code LastName FirstName 03-30-2021 06-30-2021 08-00-2021 10-30-2021
abc123 Simpson Homer 01:07 01:15 NULL 01:01
abc456 Griffen Peter 01:07 01:15 NULL 01:01
abc789 Flintsone Fred 01:07 01:15 NULL 01:01
xyz123 Heffernan Doug 01:07 01:15 NULL 01:01
xyz456 Gergich Jerry NULL NULL NULL NULL
xyz789 Kramden Ralph 01:07 01:15 NULL 01:01
The full query I am running is:
@Query AS NVARCHAR(MAX)
SELECT @cols = STUFF((SELECT DISTINCT '],[' + FORMAT(StartDate, 'dd-mm-yyyy') FROM ActualSession
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,2,'') + ']'
SET @Query = 'SELECT Code, LastName, FirstName, ' + @cols + ' FROM (
SELECT i.Code, aa.LastName, aa.FirstName, FORMAT(StartDate, ''dd-mm-yyyy'') AS StartDate, FORMAT(s.SignOut-s.SignIn, ''hh:mm'') AS AttendanceTime
FROM ActualSession AS a INNER JOIN ActualAttendee aa ON( a.id = aa.ActualSessionId)
INNER JOIN Attendee att ON (att.Id = aa.AttendeeId)
LEFT JOIN SignIn s ON (a.Id = s.ActualSessionId) LEFT JOIN Identification i ON (i.AttendeeId = aa.AttendeeId
AND i.IdentificationTypeId = (SELECT Id FROM IdentificationType WHERE [Name] = ''Student Code''))
) x PIVOT ( max(AttendanceTime)
FOR StartDate in (' + @cols + ') ) p '
PRINT @Query --for debugging
execute @Query
Relevant Table definitions are:
CREATE TABLE [dbo].[ActualSession](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[EventId] [bigint] NOT NULL,
[EventName] [nvarchar](50) NOT NULL,
[EventSessionId] [bigint] NOT NULL,
[StartDate] [datetime] NOT NULL,
[EndDate] [datetime] NOT NULL,
[Active] [bit] NULL,
[SignInRequired] [bit] NULL,
[SignOutRequired] [bit] NULL,
[SignInAllowed] [bit] NULL,
[SignOutAllowed] [bit] NULL,
[EarlySignInAllowed] [bit] NULL,
[EarlySignOutAllowed] [bit] NULL,
[LateSignInAllowed] [bit] NULL,
[LateSignOutAllowed] [bit] NULL,
[ExpiredIdAllowed] [bit] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Attendee](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[PreferredName] [nvarchar](50) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[SignIn](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[EventId] [bigint] NOT NULL,
[ActualSessionId] [bigint] NOT NULL,
[AttendeeId] [bigint] NOT NULL,
[SignIn] [datetime] NOT NULL,
[SignOut] [datetime] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Identification](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[AttendeeId] [bigint] NOT NULL,
[IdentificationTypeId] [bigint] NOT NULL,
[Code] [nvarchar](50) NOT NULL,
[ExpiryDate] [date] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[IdentificationType](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[RevHex] [bit] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[ActualAttendee](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[EventId] [bigint] NOT NULL,
[ActualSessionId] [bigint] NOT NULL,
[AttendeeId] [bigint] NOT NULL,
[FirstName] [nvarchar](50) NULL,
[LastName] [nvarchar](50) NULL,
[PreferredName] [nvarchar](50) NULL,
[GroupId] [bigint] NULL,
[GroupName] [nvarchar](50) NULL,
[GroupTypeId] [bigint] NULL,
[GroupTypeName] [nvarchar](50) NULL,
[GroupTypeAD] [bit] NULL,
[GroupTypeADName] [nvarchar](200) NULL,
[GroupTypeDB] [bit] NULL,
[GroupTypeDBQuery] [nvarchar](1000) NULL,
[GroupTypeManual] [bit] NULL
) ON [PRIMARY]
GO