簡體   English   中英

計算兩個日期之間每月的天數-SQL

[英]Count number of days per month between two dates - SQL

我對SQL還是很陌生,所以如果我使用了錯誤的術語並且我編寫的代碼太可怕了,請您道歉。

我正在嘗試創建查詢以輸出每年每月的天數。 我創建的測試表是datetest

startdate    enddate
2105-12-16   2016-02-15
2017-01-01   2017-01-02

並使用下面粘貼的查詢,我得到以下結果:

Year  Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec
2015  31   15   0    0    0    0    0    0    0    0    0    16
2017  4    0    0    0    0    0    0    0    0    0    0    0

我遇到的問題是,當日期范圍超過兩年時,結果屬於開始日期年份,而不是實際年份。

如果有人可以幫忙,我將非常感謝


查詢

SELECT
year(startdate) AS Year,

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-01-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-01-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-01-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-01-01') AS DATETIME),startdate))+1,0)) AS "Jan",

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-02-28') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-02-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-02-28') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-02-01') AS DATETIME),startdate))+1,0)) AS "Feb",

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-03-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-03-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-03-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-03-01') AS DATETIME),startdate))+1,0)) AS "Mar",

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-04-30') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-04-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-04-30') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-04-01') AS DATETIME),startdate))+1,0)) AS "Apr",

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-05-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-05-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-05-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-05-01') AS DATETIME),startdate))+1,0)) AS "May",

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-06-30') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-06-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-06-30') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-06-01') AS DATETIME),startdate))+1,0)) AS "Jun",

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-07-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-07-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-07-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-07-01') AS DATETIME),startdate))+1,0)) AS "Jul",

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-08-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-08-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-08-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-08-01') AS DATETIME),startdate))+1,0)) AS "Aug",

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-09-30') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-09-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-09-30') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-09-01') AS DATETIME),startdate))+1,0)) AS "Sep",

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-10-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-10-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-10-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-10-01') AS DATETIME),startdate))+1,0)) AS "Oct",

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-11-30') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-11-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-11-30') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-11-01') AS DATETIME),startdate))+1,0)) AS "Nov",

SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(startdate), '-12-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(startdate), '-12-01') AS DATETIME),startdate))+1,0))+SUM(GREATEST(datediff(least(CAST(CONCAT(YEAR(enddate), '-12-31') AS DATETIME),enddate),greatest(CAST(CONCAT(YEAR(enddate), '-12-01') AS DATETIME),startdate))+1,0)) AS "Dec"

from datetest

GROUP BY year(startdate)

所以我知道您不是在使用sql-server來查看語法,因此此概念可能對您有用,也可能不取決於您擁有的rdbms。 但是,概念是創建兩個日期之間差異最大的計數表,然后使用該表連接到原始表並將日期范圍展平到各個行,然后簡單地將信息旋轉回去。

DECLARE @Table AS TABLE (startdate DATETIME, enddate DATETIME)
INSERT INTO @Table (startdate, enddate) VALUES ('2015-12-16','2016-02-15'),('2017-01-01','2017-01-02')

;WITH cteTally as (
    SELECT MAX(DATEDIFF(day,startdate,enddate)) - 1 as Tally
    FROM
       @Table

    UNION ALL

    SELECT Tally - 1
    FROM
       cteTally
    WHERE
       Tally - 1 >= 0
)

, cteDates AS (
    SELECT
       DATEADD(day,c.Tally,t.startdate) as date
       ,YEAR(DATEADD(day,c.Tally,t.startdate)) as [Year]
       ,LEFT(DATENAME(month,DATEADD(day,c.Tally,t.startdate)),3) as [Month]
    FROM
       @Table t
       INNER JOIN cteTally c
       ON DATEDIFF(day,t.startdate,t.enddate) - 1 >= c.Tally
)

SELECT *
FROM
    cteDates
    PIVOT (
       COUNT([date])
       for [Month] IN ([Jan],[Feb],[Mar],[Apr],[May],[Jun],[Jul],[Aug],[Sep],[Oct],[Nov],[Dec])
    ) p

oracle,postgressql和sql-server支持這種類型的結構,而mysql則不支持。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM