2009-06-24 92 views
3

我有一张表,其中包含两列,一列用于开始日期,另一列用于结束日期。我需要编写一个查询,该查询将为每年的每个月返回一列,如果月份在0之内,那么该列的值为1。 PIVOT声明似乎是我在这里寻找的内容,但从最好的角度来看,我可以告诉PIVOT子句正在寻找匹配值,而不是检查值是否在两个其他值之间。在这里,PIVOT条款是正确的结构,还是我需要分解并编写12个案例陈述,然后汇总这些陈述​​?基于两列之间的值的SQL数据透视表

回答

2

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

  1. 获取的日期在每12个月
  2. 检查,如果这个日期开始和结束日期之间
  3. PIVOT结果

要获得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日期来滤除不属于那个月的任何条目。因此,像这样:

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 

我已经去掉了所有的其他复杂的我经历了加盟在我需要的其他信息中,所以这实际上并不是我写的查询,但它应该封装我用来根据需要获取结果的基本查询结构。

0

我会去12个案例的陈述。

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

0

为什么不计算月份的列,然后用它来转折?

日期部分(月,[日])

还是我误解了问题?