[英]Sql dynamic columns with different queries
我正在使用Microsoft SQL Server2008。我有一些非常特殊的任务,我真的希望你们能在此方面为我提供帮助,而且这在技术上是可能的...
每个人都有自己的讲座,可以选择一条等待线路,以便可以在等待名单中注册。 等待线必须是动态的。 这样,对于每一次大会,我都可以说我有2条电话或者3或4条电话,依此类推。
我需要的概述是与人有关的每条等待线的一列,相对于当前日期时间为“演讲开始日期”。 所有以过去为起点的讲座均应忽略。
我已经为该http://sqlfiddle.com/#!3/120ef创建了一个sqlfiddle
如果小提琴被更改或损坏,这里是结构,数据和选择。 http://filex02.mcon-mannheim.de/public.php?service=files&t=da4e6fc71cdf30804cb5f51b843ce368
对于每个车道,我都可以使用这样的查询(您可以将其用作小提琴)
所以对于所有等待的行,我需要这样的4个查询
SELECT p.Firstname+' '+p.Lastname as Lane1 --, *
FROM WaitingLine wLine
JOIN WaitingList wList ON wLine.WaitingLaneID = wList.WaitingLineID
JOIN Person p ON wList.PersonID = p.PersonID
JOIN Lecture l ON wList.LectureID = l.LectureID
WHERE wLine.Name = 'Lane1' AND l.StartDate > GETDATE()
AND wList.Called = 0
ORDER BY l.StartDate
ASC;
SELECT p.Firstname+' '+p.Lastname as Lane2 --, *
FROM WaitingLine wLine
JOIN WaitingList wList ON wLine.WaitingLineID = wList.WaitingLineID
JOIN Person p ON wList.PersonID = p.PersonID
JOIN Lecture l ON wList.LectureID = l.LectureID
WHERE wLine.Name = 'Lane2' AND l.StartDate > GETDATE()
AND wList.Called = 0
ORDER BY l.StartDate ASC;
SELECT p.Firstname+' '+p.Lastname as Lane3 --, *
FROM WaitingLine wLine
JOIN WaitingList wList ON wLine.WaitingLineID = wList.WaitingLineID
JOIN Person p ON wList.PersonID = p.PersonID
JOIN Lecture l ON wList.LectureID = l.LectureID
WHERE wLine.Name = 'Lane3' AND l.StartDate > GETDATE()
AND wList.Called = 0
ORDER BY l.StartDate ASC;
SELECT p.Firstname+' '+p.Lastname as Lane4 --, *
FROM WaitingLine wLine
JOIN WaitingList wList ON wLine.WaitingLineID = wList.WaitingLineID
JOIN Person p ON wList.PersonID = p.PersonID
JOIN Lecture l ON wList.LectureID = l.LectureID
WHERE wLine.Name = 'Lane4' AND l.StartDate > GETDATE()
AND wList.Called = 0
ORDER BY l.StartDate ASC;
您可以在这里看到此查询的结果:
我需要的只是一个单独的语句,其结果如下:
请注意 ,带内容的通道都不应该以NULL开头。 所有名称都需要在其演讲的开始/开始日期之前进行排序,并且输出应在每列的第一行中开始
这是我使用的表:
表: WaitingLine
表: WaitingList
表: 人
http://img829.imageshack.us/img829/194/u67b.png
表: 讲座
http://img607.imageshack.us/img607/7520/1tap.png
谢谢
如果需要使用动态列获取结果,则需要恢复为动态查询创建。 请尝试以下查询:
询问
Declare @Values as nvarchar(max)
DECLARE @query AS NVARCHAR(MAX)
Select @values = COALESCE(@Values + ',', '') + name FROM
(select distinct Name from WaitingLine) as t order by Name
Select @query = 'SELECT * ' +' from (SELECT wline.Name, FirstName+Lastname as who,
Row_number() over (partition by wline.Name order by l.startdate) as rowX
FROM WaitingLine wLine
Left outer JOIN WaitingList wList ON wLine.WaitingLineID = wList.WaitingLineID
left outer JOIN Person p ON wList.PersonID = p.PersonID
left outer join Lecture l ON wList.LectureID = l.LectureID
WHERE (l.StartDate > GETDATE() or l.StartDate is null)
AND (wList.Called = 0 or wList.Called is null) ) as t
pivot
(
max(who)
for name in ( '+ @values + ')
) as p'
execute (@query)
结果
rowX Lane1 Lane2 Lane3 Lane4
1 BruceLee MarcusReis JohnSmith NULL
2 NULL ChuckNorris JohnDoe NULL
3 NULL BruceLee SilentBob NULL
4 NULL NULL BruceLee NULL
它将为您提供所需的结果,外加一列; 希望不会给您带来麻烦。 在WHERE语句中使用OR的目的是确保您获得了Lane4记录(不包含记录)-但最后,您可以删除条件-无任何后果-我需要检查发生的事情,因此它几乎与您的查询相同。 例如,您可能考虑制作一个View,然后对其进行透视-它也可以工作,并且将使整个解决方案更加紧凑。
下面的查询可以满足您的要求,但是可能会有更优雅和可扩展的实现。 除了您提供的数据集外,我没有在其他任何数据集上进行过测试,我建议您对实际数据进行测试。 我在子查询中留下了多余的字段供您检查数据,但是一旦您满意就应该将其删除。 它们是:-wLine.Name AS Lane和l.StartDate。 话虽这么说,享受!
查询:
SELECT Lane1, Lane2, Lane3, Lane4
FROM
(
SELECT p.Firstname+' '+p.Lastname Lane1, wLine.Name AS Lane, ROW_NUMBER() OVER (ORDER BY l.StartDate) AS rn, l.StartDate
FROM WaitingLine wLine
JOIN WaitingList wList ON wLine.WaitingLaneID = wList.WaitingLineID
JOIN Person p ON wList.PersonID = p.PersonID
JOIN Lecture l ON wList.LectureID = l.LectureID
WHERE l.StartDate > GETDATE()
AND wList.Called = 0
AND wLine.Name = 'Lane1'
) Lane1
FULL OUTER JOIN
(
SELECT p.Firstname+' '+p.Lastname Lane2, wLine.Name AS Lane, ROW_NUMBER() OVER (ORDER BY l.StartDate) AS rn, l.StartDate
FROM WaitingLine wLine
JOIN WaitingList wList ON wLine.WaitingLaneID = wList.WaitingLineID
JOIN Person p ON wList.PersonID = p.PersonID
JOIN Lecture l ON wList.LectureID = l.LectureID
WHERE l.StartDate > GETDATE()
AND wList.Called = 0
AND wLine.Name = 'Lane2'
) Lane2
ON Lane1.rn = Lane2.rn
FULL OUTER JOIN
(
SELECT p.Firstname+' '+p.Lastname Lane3, wLine.Name AS Lane, ROW_NUMBER() OVER (ORDER BY l.StartDate) AS rn, l.StartDate
FROM WaitingLine wLine
JOIN WaitingList wList ON wLine.WaitingLaneID = wList.WaitingLineID
JOIN Person p ON wList.PersonID = p.PersonID
JOIN Lecture l ON wList.LectureID = l.LectureID
WHERE l.StartDate > GETDATE()
AND wList.Called = 0
AND wLine.Name = 'Lane3'
) Lane3
ON ( Lane1.rn = Lane3.rn
OR Lane2.rn = Lane3.rn)
FULL OUTER JOIN
(
SELECT p.Firstname+' '+p.Lastname Lane4, wLine.Name AS Lane, ROW_NUMBER() OVER (ORDER BY l.StartDate) AS rn, l.StartDate
FROM WaitingLine wLine
JOIN WaitingList wList ON wLine.WaitingLaneID = wList.WaitingLineID
JOIN Person p ON wList.PersonID = p.PersonID
JOIN Lecture l ON wList.LectureID = l.LectureID
WHERE l.StartDate > GETDATE()
AND wList.Called = 0
AND wLine.Name = 'Lane4'
) Lane4
ON ( Lane1.rn = Lane4.rn
OR Lane2.rn = Lane4.rn
OR Lane3.rn = Lane4.rn)
结果:
Lane1 Lane2 Lane3 Lane4
Bruce Lee Marcus Reis John Smith NULL
NULL Chuck Norris John Doe NULL
NULL Bruce Lee Silent Bob NULL
NULL NULL Bruce Lee NULL
按照下面Daniels的回答,要添加动态元素,您可以尝试在另一个查询中构建它,然后使用EXECUTE
或sp_execute
来运行它,但请记住这种方法有优缺点-我衷心建议您阅读本文 。 这是我对使用sp_executesql
的动态sql方法的看法: 查询:
DECLARE @columns AS NVARCHAR(4000)
SELECT @columns = COALESCE(@columns + ',', '') + name
FROM WaitingLine
ORDER BY Name
--SELECT @columns--
DECLARE @stmt AS NVARCHAR(4000)
DECLARE @params nvarchar(4000)
DECLARE @startdate DATETIME
SET @startdate = GETDATE()
SET @params = N'@sd DATETIME'
SET @stmt = N'SELECT '+@columns+'
FROM (SELECT wline.Name AS LaneName
, FirstName + '' '' + Lastname AS PersonFullName
, Row_number() over (partition by wline.Name order by l.startdate) AS rn
FROM WaitingLine wLine
LEFT JOIN WaitingList wList
ON wLine.WaitingLaneID = wList.WaitingLineID
LEFT JOIN Person p
ON wList.PersonID = p.PersonID
LEFT JOIN Lecture l
ON wList.LectureID = l.LectureID
WHERE l.StartDate > @sd
AND wList.Called = 0) AS src
PIVOT (MAX(PersonFullName) FOR LaneName IN ('+@columns+')) AS pvt'
EXEC sp_executesql @stmt, @params, @sd=@startdate
结果:
Lane1 Lane2 Lane3 Lane4
Bruce Lee Marcus Reis John Smith NULL
NULL Chuck Norris John Doe NULL
NULL Bruce Lee Silent Bob NULL
NULL NULL Bruce Lee NULL
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.