具有不同查询的Sql动态列

时间:2014-03-05 12:32:07

标签: sql sql-server

我正在使用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;

您可以在此处看到此查询的结果:

enter image description here

我需要的只是一个结果如下的单一陈述:

enter image description here

请注意,没有包含内容的通道应以NULL开头。所有名称都需要在讲座的开始/开始日期排序,输出应从每列的第一行开始

以下是我使用的表格:

表: WaitingLine

enter image description here

表:等待列表

enter image description here

表:

http://img829.imageshack.us/img829/194/u67b.png

表:讲座

http://img607.imageshack.us/img607/7520/1tap.png

感谢

2 个答案:

答案 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在下面的回答,要添加您需要的动态元素,您可以尝试在另一个查询中构建它,然后使用EXECUTEsp_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