2016-08-20 4 views
0

Я очень новичок в 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) 
+1

, который rdbms? sql-server, mysql, oracel, ...? – Matt

+0

'2105-12-16'? Должен ли это быть годом * до * 2016 года? – wallyk

+0

im sure ur что-то ужасное: d –

ответ

1

, так что я знаю, что вы не используете SQL-сервер, глядя на свой синтаксис, так эта концепция могла бы работать для вас или нет в зависимости от 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 

оракул, PostgresSQL, а также поддержка SQL-сервер этого типа структуры, где, как MySQL не будет.

Смежные вопросы