繁体   English   中英

具有不同查询的SQL动态列

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM