2015-11-03 229 views
1

下午好, 我有一個看起來像一個簡單的問題,結果並不那麼簡單。我有兩個約會。 BeginPeriod(2010-06-10)和EndPeriod(2011-06-11)。SQL拆分期間每月

我想看看這些日期是否可以分解成它們各自的月度分解點。對於上面的例子像

  • 2010/06/10 - 2010/06/30
  • 2010/07/01 - 2010/07/31
  • 2010/08/01 - 2010/08/31
  • ............
  • 2011/06/01 - 2011/06/10

我不講究方法。 CTE很好,但不是首選。正如他們所說,乞丐不能是選擇者。

一切順利, 喬治

+0

當你試圖實現這個功能時,你遇到了什麼問題? – HABO

回答

6

CTE它。

DECLARE @BeginPeriod DATETIME = '2010-06-10', 
     @EndPeriod DATETIME = '2011-06-11' 

;WITH cte AS 
(
    SELECT DATEADD(month, DATEDIFF(month, 0, @BeginPeriod), 0) AS StartOfMonth, 
      DATEADD(s, -1, DATEADD(mm, DATEDIFF(m, 0, @BeginPeriod) + 1, 0)) AS EndOfMonth 
    UNION ALL 
    SELECT DATEADD(month, 1, StartOfMonth) AS StartOfMonth, 
      DATEADD(s, -1, DATEADD(mm, DATEDIFF(m, 0, DATEADD(month, 1, StartOfMonth)) + 1, 0)) AS EndOfMonth 
    FROM cte 
    WHERE DATEADD(month, 1, StartOfMonth) <= @EndPeriod 
) 
SELECT 
    (CASE WHEN StartOfMonth < @BeginPeriod THEN @BeginPeriod ELSE StartOfMonth END) StartOfMonth, 
    (CASE WHEN EndOfMonth > @EndPeriod THEN @EndPeriod ELSE EndOfMonth END) EndOfMonth 
FROM cte 

最後EndOfMonth是,如果你想前一天

您可以使用此修剪的時候你作爲@EndPeriod其設置爲DATEADD(day, -1, @EndPeriod)值。

SELECT 
    CONVERT(VARCHAR(10), (CASE WHEN StartOfMonth < @BeginPeriod THEN @BeginPeriod ELSE StartOfMonth END), 120) StartOfMonth, 
    CONVERT(VARCHAR(10), (CASE WHEN EndOfMonth > @EndPeriod THEN @EndPeriod ELSE EndOfMonth END), 120) EndOfMonth 
FROM cte 
+0

感謝您的正確答案。對此,我真的非常感激。它像一個魅力。 –

+0

感謝提醒我關於遞歸CTE,幫助我在另一個類似的問題上獲得一些聲譽:) – shurik

0

與「數字」的另一個選項CTE

 
declare @df datetime, @dt datetime 
set @df = '20100610' 
set @dt = '20110611' 

;WITH e1(n) AS 
(
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
), -- 10 
e2(n) AS (SELECT ROW_NUMBER() OVER (ORDER BY e1.n) FROM e1 CROSS JOIN e1 AS b) -- 10*10 
select 
    case when e2.n = 1 
     then @df 
     else dateadd(day, -day(@df) + 1, dateadd(month, e2.n - 1, @df)) end, 
    case when e2.n = datediff(month, @df, @dt) + 1 
     then dateadd(month, e2.n -1 , @df) 
     else EOMONTH(dateadd(month, e2.n -1 , @df)) end 
from e2 
where e2.n

不是數字CTE可以使用例如一些其他的選擇,因爲這裏所描述 http://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1 我經常Numbers表格在我的數據庫此類任務的。我認爲主要是因爲我在將CTE添加到MS SQL之前就開始使用這種技術,但它的輸入也較少。