每月数据量

时间:2019-08-12 09:52:36

标签: sql sql-server

我必须计算每月的每日汽车数量 我尝试使用Datediff公式执行此操作 但是我也不能添加每个月的细分。

附加的脚本表:

create table TABLE_A(Code FLOAT,DateIn datetime,dateOut datetime,Garage varchar(30) 
  )
  insert into Table_A (Code,DateIn,dateOut,Garage) values 
  ('1','2018-06-07 00:00:00.000','2018-12-19 00:00:00.000','X'),
  ('2','2018-05-30 00:00:00.000','2018-12-19 00:00:00.000','Y'),
  ('3','2018-08-08 00:00:00.000','2018-11-18 00:00:00.000','Z'),
  ('4','2018-12-30 00:00:00.000','2018-12-30 00:00:00.000','Y'),
  ('5','2018-09-16 00:00:00.000','2018-10-19 00:00:00.000','Y'),
  ('6','2018-05-08 00:00:00.000','2018-08-28 00:00:00.000','Z'),
  ('7','2018-01-29 00:00:00.000','2018-07-31 00:00:00.000','Z'),
  ('8','2018-05-24 00:00:00.000','2018-09-10 00:00:00.000','X'),
  ('9','2018-05-02 00:00:00.000','2018-06-30 00:00:00.000','Y'),
  ('10','2018-07-05 00:00:00.000','2018-12-09 00:00:00.00','Z')

这是查询结果的结构,其结构应为:(列:年,月,车库-每天按天计算的车辆数量)

Year     month        X     Y       Z

2018     1          
2018     2          
2018     3          
2018     4          
2018     5          
2018     6          
2018     7          
2018     8          
2018    9           
2018     10         
2018     11         
2018    12              

感谢您的帮助。

4 个答案:

答案 0 :(得分:0)

以下脚本仅在特定记录的所有DateIn和DateOut都在同一年(如2018年)时起作用。

  

Le年不考虑年份,但可以实施。

WITH Month_Wise_Day AS
(
    -- Listing/selecting 12 month manually here
    -- With number of day for that month
    SELECT 1 M, 31 ND UNION ALL
    SELECT 2 M, 28 UNION ALL SELECT 3 M,31 UNION ALL SELECT 4 M,30 UNION ALL SELECT 5 M,31 UNION ALL
    SELECT 6 M,30 UNION ALL SELECT 7 M,31 UNION ALL SELECT 8 M,31 UNION ALL SELECT 9 M,30 UNION ALL
    SELECT 10 M,31 UNION ALL SELECT 11 M,30 UNION ALL SELECT 12 M,31
) 

SELECT A.Year, A.Month,
SUM(CASE WHEN A.Garage = 'X' THEN A.No_of_days ELSE 0 END) AS X,
SUM(CASE WHEN A.Garage = 'Y' THEN A.No_of_days ELSE 0 END) AS Y,
SUM(CASE WHEN A.Garage = 'Z' THEN A.No_of_days ELSE 0 END) AS Z
FROM 
(
    SELECT A.*,
    B.M AS Month,
    YEAR(A.DateIn) AS Year,
    CASE 
        WHEN MONTH(A.DateIn) = MONTH(A.DateOut) THEN DATEDIFF(DD,DateIn,DateOut) +1
        WHEN B.M = MONTH(DateIn) THEN B.ND - DAY(DateIn)+1 
        WHEN B.M = MONTH(DateOut) THEN DAY(DateOut)
        ELSE ND 
    END No_of_days
    FROM TABLE_A A
    INNER JOIN Month_Wise_Day B ON B.M BETWEEN MONTH(DateIn) AND MONTH (DateOut) 
)A
GROUP BY A.Year, A.Month

答案 1 :(得分:0)

您可以首先生成月份和年份的列表,然后可以将表加入该列表-

WITH MONTHS AS (SELECT 1 MNTHS
                UNION ALL
                SELECT 2
                UNION ALL
                SELECT 3
                UNION ALL
                SELECT 4
                UNION ALL
                SELECT 5
                UNION ALL
                SELECT 6
                UNION ALL
                SELECT 7
                UNION ALL
                SELECT 8
                UNION ALL
                SELECT 9
                UNION ALL
                SELECT 10
                UNION ALL
                SELECT 11
                UNION ALL
                SELECT 12),
  YEAR AS (SELECT 2018 YEAR)
SELECT YEAR,
       MNTHS,
       SUM(CASE WHEN Garage = 'X' THEN 1 ELSE 0 END) AS X,
       SUM(CASE WHEN Garage = 'Y' THEN 1 ELSE 0 END) AS Y,
       SUM(CASE WHEN Garage = 'Z' THEN 1 ELSE 0 END) AS Z
FROM (SELECT * FROM MONTHS M CROSS JOIN YEAR Y) YEARS
LEFT JOIN TABLE_A T ON YEARS.MNTHS = MONTH(T.DateIn)
                    AND YEARS.YEAR = YEAR(T.DateIn)
GROUP BY YEAR(DateIn),
         MONTH(DateIn),
         MNTHS,
         YEAR
ORDER BY YEAR,
         MNTHS

这里是fiddle

答案 2 :(得分:0)

您可以使用递归子查询生成日期。

然后,您可以采用多种方法来计算摘要数据。一种简单的方法使用apply

with dates as (
      select convert(date, '2018-01-01') as dte, 1 as lev
      union all
      select dateadd(month, 1, dte), lev + 1
      from dates
      where lev < 12
     )
select year(d.dte), month(d.dte), s.*
from dates d outer apply
     (select sum(case when a.Garage = 'X' then 1 else 0 end) as x,
             sum(case when a.Garage = 'Y' then 1 else 0 end) as y,
             sum(case when a.Garage = 'Z' then 1 else 0 end) as z
      from table_a a
      where a.datein <= d.dte and a.dateout >= d.dte
     ) s;

您的问题对确切的计算有点模糊。这样可以计算出每个月第一天每个车库中的汽车数量。

Here是db <>小提琴。

编辑:

您修改后的问题更加复杂,但是自从我开始回答:

with dates as (
      select convert(date, '2018-01-01') as dte, 1 as lev
      union all
      select dateadd(month, 1, dte), lev + 1
      from dates
      where lev < 12
     )
select year(d.dte), month(d.dte),
       sum(case when a.Garage = 'X' 
                then datediff(day,
                              (case when a.datein < d.dte then d.dte else datein end),
                              (case when a.dateout >= dateadd(month, 1, d.dte) then eomonth(d.dte) else dateout end)
                             ) + 1
                else 0
           end) as x_cardays,
       sum(case when a.Garage = 'Y' 
                then datediff(day,
                              (case when a.datein < d.dte then d.dte else datein end),
                              (case when a.dateout >= dateadd(month, 1, d.dte) then eomonth(d.dte) else dateout end)
                             ) + 1
                else 0
           end) as y_cardays,
       sum(case when a.Garage = 'Z' 
                then datediff(day,
                              (case when a.datein < d.dte then d.dte else datein end),
                              (case when a.dateout >= dateadd(month, 1, d.dte) then eomonth(d.dte) else dateout end)
                             ) + 1
                else 0
           end) as z_cardays
from (select d.*, day(eomonth(dte)) as days_in_month
      from dates d
     ) d left join
     table_a a
     on a.datein < dateadd(month, 1, d.dte) and a.dateout >= d.dte
group by d.dte
order by d.dte;

与日期重叠有点棘手,但您绝对想对日期进行重叠。

请注意,这不是每天的平均值。如果需要平均值,可以除以d.days_in_month

Here是经过修改的db <>小提琴。

答案 3 :(得分:0)

以下查询应做您想做的事情,Recursive CTE部分用于确定每个DayInDayOut之间的日期。有了完整的日期列表后,在主查询中,我们将进行条件汇总,以找出每月DISTINCT个车库中的汽车数量

CREATE TABLE TABLE_A (Code FLOAT,DateIn DATETIME,dateOut DATETIME,Garage VARCHAR(30))
INSERT INTO Table_A (Code,DateIn,dateOut,Garage) VALUES
('1','2018-06-07 00:00:00.000','2018-12-19 00:00:00.000','X'),
('2','2018-05-30 00:00:00.000','2018-12-19 00:00:00.000','Y'),
('3','2018-08-08 00:00:00.000','2018-11-18 00:00:00.000','Z'),
('4','2018-12-30 00:00:00.000','2018-12-30 00:00:00.000','Y'),
('5','2018-09-16 00:00:00.000','2018-10-19 00:00:00.000','Y'),
('6','2018-05-08 00:00:00.000','2018-08-28 00:00:00.000','Z'),
('7','2018-01-29 00:00:00.000','2018-07-31 00:00:00.000','Z'),
('8','2018-05-24 00:00:00.000','2018-09-10 00:00:00.000','X'),
('9','2018-05-02 00:00:00.000','2018-06-30 00:00:00.000','Y'),
('10','2018-07-05 00:00:00.000','2018-12-09 00:00:00.00','Z')

    /** Main Query Starts Here **/

;WITH CTE ([Code],[DateIn],[DateOut],[Garage]) AS (
    SELECT [Code], [DateIn], [DateOut], [Garage]
    FROM TABLE_A WHERE [DateIn] <= [DateOut]

    UNION ALL

    SELECT [Code], DATEADD(DAY, 1, [DateIn]), [DateOut], [Garage]
    FROM CTE 
    WHERE [DateIn] < [DateOut])

SELECT 
    YEAR([DateIn]) AS [Year]
    ,MONTH([DateIn]) AS [Month]
    ,COUNT( DISTINCT CASE WHEN [Garage] = 'X' THEN T.t1 ELSE NULL END) AS X
    ,COUNT( DISTINCT CASE WHEN [Garage] = 'Y' THEN T.t1 ELSE NULL END) AS Y
    ,COUNT( DISTINCT CASE WHEN [Garage] = 'Z' THEN T.t1 ELSE NULL END) AS Z
FROM CTE 
CROSS APPLY (VALUES (CONVERT(VARCHAR(4),YEAR([DateIn])) + CONVERT(VARCHAR(2),MONTH([DateIn])) + CONVERT(VARCHAR(20),[Code]))) AS T(t1)
GROUP BY YEAR([DateIn]), MONTH([DateIn])
ORDER BY [Year], [Month]
OPTION (MAXRECURSION 0)

结果如下,

Year    Month   X   Y   Z
2018    1       0   0   1
2018    2       0   0   1
2018    3       0   0   1
2018    4       0   0   1
2018    5       1   2   2
2018    6       2   2   2
2018    7       2   1   3
2018    8       2   1   3
2018    9       2   2   2
2018    10      1   2   2
2018    11      1   1   2
2018    12      1   2   1