我正在使用Microsoft SQL Server 2008.我有一些非常特殊的任务,我真的希望你们可以帮助我,这是技术上的可能......
每个人都有自己的演讲,可以选择等待他可以在等候名单中注册的等候线。 等待线必须是动态的。因此,对于每个国会,我可以说我有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
表:等待列表
表:人
http://img829.imageshack.us/img829/194/u67b.png
表:讲座
http://img607.imageshack.us/img607/7520/1tap.png
感谢
答案 0 :(得分:3)
如果需要使用动态列获取结果,则需要恢复为动态查询创建。请尝试以下查询:
<强>查询强>
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为例,然后旋转它 - 它也可以工作,并使整个解决方案更加紧凑。
答案 1 :(得分:2)
下面的查询可以满足您的要求,但可能会有更优雅和可扩展的实现。 我没有在你提供的数据集上测试任何其他数据集,我建议测试实际数据。 我在子查询中留下了多余的字段供您检查数据,但是一旦您满意就应删除它们。它们是: - 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
来运行它,但请记住,这里有专家和骗子方法 - 我衷心建议您阅读此article。
这是我使用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