简体   繁体   English

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

[英]SQL query - sum of values by status for date interval

I get crazy because of one query. 我因为一个查询而发疯。 I have a table like following and I want to get a data - Summa of Values by Status For every Date in interval. 我有一个类似以下的表格,我想获取一个数据- 状态中每个日期的值总和。

Table

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

For example, 例如,

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

Output: 输出:

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)

In 01.02.14 and 02.04.14 dates, pro4 has not values by status, but I want to show that rows, because I need all dates in that interval. 01.02.1402.04.14 . 01.02.14 02.04.14日期中, pro4没有按状态显示的值,但是我想显示该行,因为我需要该间隔中的所有日期。 Can anyone help me to create this query? 谁能帮助我创建此查询?

Edit: 编辑:

I can not change structure, I have already that table with data. 我无法更改结构,我已经有了带有数据的表。 Every day exist in table many times (minimum 1 time) 每天在表中存在多次(最少1次)

Thanks in advance. 提前致谢。

Assuming you have a row for each date in the table, use conditional aggregation: 假设表中的每个日期都有一行,请使用条件聚合:

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;

If you don't have this list of dates, you can take this approach instead: 如果没有此日期列表,则可以采用以下方法:

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;

just an assumption query : 只是一个假设查询:

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 

This is not really the exact query, but I think you can get that by having a query that looks like: 这实际上不是确切的查询,但是我认为您可以通过以下查询来实现:

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

this page gives more info. 页面提供更多信息。

EDIT 编辑

So the above query only gives a part of the answer required by the OP. 因此,以上查询仅给出了OP所需答案的一部分。 A LEFT OUTER JOIN of the original table and the result of the above query on the date and status fields will give the missing info. 原始表的LEFT OUTER JOIN以及datestatus字段的上述查询结果将提供缺少的信息。

eg 例如

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;

To expand my comment the complete query is 为了扩大我的评论,完整的查询是

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

Note that the condition on the name need to be in the JOIN, otherwise you'll get only the date of your table. 请注意,名称上的条件必须在JOIN中,否则您将仅获得表格的日期。
If you need multiple years just add another CTE for the count and a dateadd(YEAR,...) in the CTE calendar 如果您需要多年,只需在CTE日历中添加另一个CTE作为计数和dateadd(YEAR,...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM