为每个组选择一个/多个行

时间:2016-11-16 08:54:06

标签: sql sql-server tsql sql-server-2012

我有一组这样的供应操作:

op_type  |  time_stamp  |  product | in  | out
----------------------------------------------------
01       |  08:00:00    | p1       | 50  | 0  
02       |  08:01:00    | p1       | 0   | 10  
02       |  08:02:00    | p1       | 0   | 35  
03       |  08:03:00    | p1       | 0   | 5  
01       |  08:04:00    | p1       | 60  | 0  
02       |  08:09:00    | p1       | 0   | 15  
01       |  08:10:00    | p1       | 30  | 0  
02       |  08:11:00    | p1       | 0   | 20  
01       |  08:00:00    | p2       | 100 | 0  
02       |  08:01:00    | p2       | 0   | 20  
02       |  08:02:00    | p2       | 0   | 45  
03       |  08:03:00    | p2       | 0   | 15  
01       |  08:03:10    | p2       | 60  | 0  
01       |  08:04:00    | p2       | 5   | 0  
02       |  08:09:00    | p2       | 0   | 30  
01       |  08:10:00    | p2       | 30  | 0  
02       |  08:11:00    | p2       | 0   | 10

我想要的是从给定时间开始选择SUM(in) group by product将涵盖SUM(out) group by product的列表 EX:对于time_stamp>'08:05:00'我有:

SUM(out) for p1=35所以总和 和SUM(out) for p2=40

所以我想要的列表是

op_type  |  time_stamp  |  product | in  | out
----------------------------------------------------
01       |  08:04:00    | p1       | 60  | 0  
02       |  08:09:00    | p1       | 0   | 15  
01       |  08:10:00    | p1       | 30  | 0  
02       |  08:11:00    | p1       | 0   | 20 
01       |  08:03:10    | p2       | 60  | 0  
01       |  08:04:00    | p2       | 5   | 0  
02       |  08:09:00    | p2       | 0   | 30  
01       |  08:10:00    | p2       | 30  | 0  
02       |  08:11:00    | p2       | 0   | 10

我所做的就是我在结果中添加了一列,其中一列的总和为out而另一列的累计总和为in

 SELECT B.*,C.sum_out  FROM (SELECT A.*,SUM(in) OVER (PARTITION BY product ORDER BY time_stamp desc) AS sum_in FROM table A) B
 LEFT OUTER JOIN 
 SELECT C.* FROM (SELECT product,SUM(out) AS sum_out from table GROUP BY product WHERE time_stamp>'08:05:00') C
 ON B.product=C.product

所以我得到了:

op_type  |  time_stamp  |  product | in  | out  | sum_in  | sum_out
-------------------------------------------------------------------------
01       |  08:00:00    | p1       | 50  | 0    | 140     | 35
02       |  08:01:00    | p1       | 0   | 10   | 90      | 35
02       |  08:02:00    | p1       | 0   | 35   | 90      | 35
03       |  08:03:00    | p1       | 0   | 5    | 90      | 35
01       |  08:04:00    | p1       | 60  | 0    | 90      | 35
02       |  08:09:00    | p1       | 0   | 15   | 30      | 35
01       |  08:10:00    | p1       | 30  | 0    | 30      | 35
02       |  08:11:00    | p1       | 0   | 20   | 0       | 35
01       |  08:00:00    | p2       | 100 | 0    | 195     | 40
02       |  08:01:00    | p2       | 0   | 20   | 95      | 40
02       |  08:02:00    | p2       | 0   | 45   | 95      | 40 
03       |  08:03:00    | p2       | 0   | 15   | 95      | 40 
01       |  08:03:10    | p2       | 60  | 0    | 95      | 40 
01       |  08:04:00    | p2       | 5   | 0    | 35      | 40
02       |  08:09:00    | p2       | 0   | 30   | 30      | 40
01       |  08:10:00    | p2       | 30  | 0    | 30      | 40
02       |  08:11:00    | p2       | 0   | 10   | 0       | 40

如果我添加条款WHERE B.sum_in<=C.sum_out我将能够获得

op_type  |  time_stamp  |  product | in  | out  | sum_in  | sum_out
-------------------------------------------------------------------------
02       |  08:09:00    | p1       | 0   | 15   | 30      | 35
01       |  08:10:00    | p1       | 30  | 0    | 30      | 35
02       |  08:11:00    | p1       | 0   | 20   | 0       | 35
01       |  08:04:00    | p2       | 5   | 0    | 35      | 40
02       |  08:09:00    | p2       | 0   | 30   | 30      | 40
01       |  08:10:00    | p2       | 30  | 0    | 30      | 40
02       |  08:11:00    | p2       | 0   | 10   | 0       | 40

所以每个产品还需要一行。

任何想法如何执行? PS:我正在使用SQL SERVER 2012。

2 个答案:

答案 0 :(得分:2)

我起草了一个可能的解决方案,您可以使用子查询来获取所有累积的交易

            Select time_stamp, 
        (Select Sum(SQ.InEntry - SQ.OutEntry)  from Table_1 AS SQ where T.time_stamp > SQ.time_stamp AND T.product = SQ.product group by product) +
            InEntry - OutEntry 
            , T.InEntry
            , T.OutEntry
            , product 
            from Table_1 T
            order by product,time_stamp

为了生成随机数据,我使用了这个语句

            declare @FromDate date = '2016-01-01'
            declare @ToDate date = '2016-12-31'
             declare @product varchar(50)
             set @product = ( select top 1  A.Prod from (Select 'A' AS Prod union all select 'B' AS Prod union all select 'C' AS Prod) AS A order by newid())

            INSERT INTO [dbo].[Table_1]
                       ([time_stamp]
                       ,[product]
                       ,[InEntry]
                       ,[OutEntry])
            Select
            dateadd(day, 
                           rand(checksum(newid()))*(1+datediff(day, @FromDate, @ToDate)), 
                           @FromDate)
            ,@product
            ,0
            ,ABS(Checksum(NewID()) % 100)


            INSERT INTO [dbo].[Table_1]
                       ([time_stamp]
                       ,[product]
                       ,[InEntry]
                       ,[OutEntry])
            Select
            dateadd(day, 
                           rand(checksum(newid()))*(1+datediff(day, @FromDate, @ToDate)), 
                           @FromDate)
            ,@product
            ,@product ,ABS(Checksum(NewID()) % 100)
            ,0
            GO 40    

答案 1 :(得分:0)

您似乎不按产品分组? 无论如何这可能会有所帮助,你可以使用SUM&amp; amp; GROUP BY对当时具有适当WHERE子句的内容进行分组。

但要得到你所要求的......

  

SUM(in)group by product将涵盖SUM(out)

....你可以使用HAVING .....

例如

SELECT Field1, Field2, SUM(IN), SUM(OUT)
FROM Table
WHERE Your_where_clause
GROUP BY Field1, Field2
HAVING SUM(IN) >= SUM(OUT)