[英]SQL pivot with unknown number of columns - not a valid identifier and showing minimum only
我的动态查询在 MS SQL Server 2014 中以未知数量的列为中心时遇到问题。我的查询基于文章SQL Server 2005 以未知数量的列和其他类似文章为基础。 但是,我有两个无法破译的问题。
执行动态 SQL 时,出现此错误:
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.
但是,如果我将查询复制并粘贴到 SQL Server Management Studio 中的单独窗口中,它会运行...我看不出有什么问题,除了错误消息仅返回查询的前 xxx 个字符。 . 任何关于我做错了什么的建议将不胜感激。 是连接还是我选择列的方式?
但是......这把我带到了第二个问题。 当我单独运行复制的查询文本时,它可以工作,但它为所有用户显示相同的值(以小时/分钟为单位的时间),而不是用户特定的值(尽管未登录的用户正确地出现了 NULL )。 枢轴似乎需要一个最小/最大/其他聚合,但它应该将它保留给每个用户(根据我所看到的,通过一些 SQL 巫术),它不是......列名似乎也即将到来以美国日期格式显示,即使我已将格式指定为澳大利亚 (dd-mm-yyyy)。 如果有人知道如何纠正这些问题,那也将不胜感激。
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
我正在运行的完整查询是:
@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
相关的表定义是:
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
我相信您收到的错误与execute @Query
而不是execute (@Query)
。 查看EXECUTE上的 Microsoft 文档,执行字符串变量需要打开和关闭括号:
Execute a character string
{ EXEC | EXECUTE }
( { @string_variable | [ N ]'tsql_string' } [ + ...n ] )
[ AS { LOGIN | USER } = ' name ' ]
[;]
一旦我添加了括号,我就能够得到我认为与您的语句等效的语句,以使用我创建的一些示例数据按预期执行。
至于你的日期格式,我相信你的日期格式字符串有问题。 我相信您当前的dd-mm-yyyy
日期格式字符串应该是dd-MM-yyyy
。 根据自定义日期和时间格式字符串Microsoft doc(由 Microsoft doc 在FORMAT
上引用):
你在这里有两个问题:
execute
您需要将@Query
括在括号()
。 不过,我建议您使用sp_executesql
,因为这使您可以在必要时传递参数QUOTENAME
DECLARE @Query AS nvarchar(MAX), @cols nvarchar(MAX);
SELECT @cols = STUFF((
SELECT DISTINCT ',' + QUOTENAME(FORMAT(StartDate, 'dd-mm-yyyy'))
FROM ActualSession
FOR XML PATH(''), TYPE
).value('text()[1]', 'NVARCHAR(MAX)')
, 1, LEN(','), '');
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
EXEC sp_executesql @Query;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.