SQL查询 - 日期间隔状态的值总和

时间:2014-04-17 12:15:49

标签: sql sql-server tsql group-by sql-order-by

我因为一个查询而变得疯狂。我有一个像下面这样的表格,我想得到一个数据 - 按状态排列的每个日期的日期值。

表格

Id    Name    Value    Date        Status
1     pro1    2        01.04.14    0 
2     pro1    8        02.04.14    1 
3     pro2    6        02.04.14    1
4     pro3    0        03.04.14    0
5     pro4    7        03.04.14    0
6     pro4    2        03.04.14    0
7     pro4    4        03.04.14    1
8     pro4    6        04.04.14    1
9     pro4    1        04.04.14    1

例如,

输入: 名称= pro4,minDate = 01.02.14,maxDate = 04.09.14

输出:

Date           Values sum for 0 Status          Values sum for 1 Status    
01.04.14       0                                0
02.04.14       0                                0
03.04.14       9   (=7+2)                       4  (only 4 exist)
04.04.14       0                                7  (6+1)

01.02.1402.04.14日期,pro4没有状态值,但我想显示这些行,因为我需要该时间间隔内的所有日期。有人可以帮我创建这个查询吗?

修改

我无法更改结构,我已经有了数据表。每天都有很多次(至少1次)存在于表中

提前致谢。

4 个答案:

答案 0 :(得分:2)

假设表中的每个日期都有一行,请使用条件聚合:

select date,
       sum(Case when name = 'pro4' and status = 0 then Value else 0 end) as values_0,
       sum(case when name = 'pro4' and status = 1 then Value else 0 end) as values_1
from Table t
where date >= '2014-04-01' and date <= '2014-04-09'
group by date
order by date;

如果您没有此日期列表,则可以采用此方法:

with dates as (
      select cast('2014-04-01' as date) as thedate
      union all
      select dateadd(day, 1, thedate)
      from dates
      where thedate < '2014-04-09'
)
select dates.thedate,
       sum(Case when status = 0 then Value else 0 end) as values_0,
       sum(case when status = 1 then Value else 0 end) as values_1
from dates left outer join
     table t
     on t.date = dates.thedate and t.name = 'pro4'
group by dates.thedate;

答案 1 :(得分:0)

只是一个假设查询:

select Distinct date ,case when status = 0 and MAX(date) then SUM(value) ELSE 0 END Status0 ,
case when status = 1 and MAX(date) then SUM(value) ELSE 0 END Status1  from table 

答案 2 :(得分:0)

这不是确切的查询,但我认为你可以通过查询看起来像这样:

select date, status, sum(value) from table
    where (date between mindate and maxdate) and name = product_name
    group by date, status;

page提供了更多信息。

修改

因此上述查询仅给出了OP所需答案的一部分。原始表格的LEFT OUTER JOIN以及datestatus字段上的上述查询结果将显示缺少的信息。

e.g。

select x.date, x.status, x.sum_of_values from table as y 
left outer join 
(select date, status, sum(value) as sum_of_values 
    from table 
    where (date between mindate and maxdate) and name = product_name 
    group by date, status) as x 
on y.date= x.date and y.status = x.status
order by x.date;

答案 3 :(得分:0)

要扩展我的评论,完整的查询是

WITH [counter](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 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 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 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1)
, days(N) AS (
  SELECT row_number() over (ORDER BY (SELECT NULL)) FROM [counter])
, months (N) AS (
  SELECT N - 1 FROM days WHERE N < 13)
, calendar ([date]) AS (
  SELECT DISTINCT cast(dateadd(DAY, days.n
                     , dateadd(MONTH, months.n, '20131231')) AS date)
  FROM months
       CROSS JOIN days
  )
SELECT a.Name
     , c.Date
     , [Sum of 0] = SUM(CASE Status WHEN 0 THEN Value ELSE 0 END)
     , [Sum of 1] = SUM(CASE Status WHEN 1 THEN Value ELSE 0 END)
FROM   Calendar c
       LEFT  JOIN myTable a ON c.Date = a.Date AND a.name = 'pro4'
WHERE  c.date BETWEEN '20140201' AND '20140904'
GROUP BY c.Date, a.Name
ORDER BY c.Date

请注意,名称上的条件必须在JOIN中,否则您只能获得表格的日期。
如果您需要多年,只需为计数添加另一个CTE,并在CTE日历中添加dateadd(YEAR,...)