SQL Pivot基于两列之间的值

时间:2009-06-24 13:11:56

标签: sql sql-server-2005 tsql

我有一张表,其中包括两列,一列用于开始日期,另一列用于结束日期。我需要编写一个查询,该查询将返回一年中每个月的列,如果月份在0之间,则该列的值为1。 PIVOT语句似乎是我在这里寻找的,但从最好的我可以告诉PIVOT子句寻找匹配值,而不是检查值是否在两个其他之间。 PIVOT子句在这里是正确的构造,还是我需要分解并编写12个案例语句然后汇总它们?

3 个答案:

答案 0 :(得分:2)

我想我在这里得到了解决方案。有3个基本步骤:

  1. 获取12个月中的每个月的日期
  2. 检查此日期是否在开始日期和结束日期之间
  3. PIVOT结果
  4. 为了获得12个日期,每个月一个,我使用一些递归式的WITH语句来创建一个包含12列日期的1列的临时表:

    WITH months (date) AS (
    SELECT GETDATE() AS date
    UNION ALL
    SELECT 
        DATEADD(MONTH,1,date)
    FROM months
    WHERE DATEDIFF(MONTH,GETDATE(),date) < 12)
    

    从这里我可以CROSS JOIN这个临时表与表格,我真正关心的信息。然后我使用WHERE日期BETWEEN开始和结束来过滤掉那些不属于那个月的条目。所以像这样:

    SELECT other.Title, MONTH(months.date) CROSS JOIN other
    WHERE months.date BETWEEN other.start AND other.end
    

    在这一步中,我们必须小心只选择结果中明确需要的列,或者使用PIVOT语句聚合的列。

    最后,我们必须调整结果:

    PIVOT (MAX(PID) FOR date IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12]))
    

    因此,结果查询可能类似于:

    WITH months (date) AS (
    SELECT GETDATE() AS date
    UNION ALL
    SELECT 
    DATEADD(MONTH,1,date)
    FROM months
    WHERE DATEDIFF(MONTH,GETDATE(),date) < 12)
    SELECT  Title,
        [1]     AS January,
        [2]     AS February,
        [3]     AS March,
        [4]     AS April,
        [5]     AS May,
        [6]     AS June,
        [7]     AS July,
        [8]     AS August,
        [9]     AS September,
        [10]    AS October,
        [11]    AS November,
        [12]    AS December
    FROM
    (
    SELECT other.Title,MONTH(months.date)
    CROSS JOIN other
    WHERE months.date BETWEEN other.startDate AND other.endDate
    ) AS subquery
    PIVOT (MAX(PID) FOR date IN
    ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) AS p
    

    我已经删除了我所需要的所有其他复杂性以加入我需要的其他信息,所以这实际上不是我写的查询,但它应该封装我用来获得结果的基本查询结构因为我需要它。

答案 1 :(得分:0)

我会选择12个案例陈述。

这实际上是我在回去之前勾勒出的解决方案,看到你在其中提到了你的问题。

答案 2 :(得分:0)