SQL查询从累积数据中获取单个值

时间:2012-02-08 18:49:55

标签: sql

以下示例数据具有每个条目的累积大小。我正在尝试编写一个查询来更新大小,大小与前一个时间戳的差异(例如 - 第2行应更新为(4478.74 - 4476)= 2.74)对于相同的项目名称。请帮我解决这个问题。

Row Item     Size       Time
-----------------------------------------------
1   ItemA    4476       7/01/2012 11:15
2   ItemA    4478.74    7/01/2012 11:20
3   ItemA    4478.82    7/01/2012 11:21
4   ItemA    4487.51    7/01/2012 11:29
5   ItemB    1.53       7/01/2012 11:29
6   ItemB    1.67       7/01/2012 11:20
7   ItemB    1.84       7/01/2012 11:21
8   ItemB    2.18       7/01/2012 11:15

2 个答案:

答案 0 :(得分:2)

您可以按项目对数据进行分区,然后将其外部连接到上一行编号:

    create table ItemTotal (id uniqueidentifier, item varchar(10), size numeric(10,2), entry datetime)

    insert into ItemTotal values(NEWID(), 'ItemA', 4476, '7/01/2012 11:15');
    insert into ItemTotal values(NEWID(), 'ItemA', 4478.74, '7/01/2012 11:20');
    insert into ItemTotal values(NEWID(), 'ItemA', 4478.82, '7/01/2012 11:21');
    insert into ItemTotal values(NEWID(), 'ItemA', 4487.51, '7/01/2012 11:29');
    insert into ItemTotal values(NEWID(), 'ItemB', 1.53, '7/01/2012 11:29');
    insert into ItemTotal values(NEWID(), 'ItemB', 1.67, '7/01/2012 11:20');
    insert into ItemTotal values(NEWID(), 'ItemB', 1.84, '7/01/2012 11:21');
    insert into ItemTotal values(NEWID(), 'ItemB', 2.18, '7/01/2012 11:15');

    with items(id, item, size, entry, rn) as (
    select id, item, size, entry, ROW_NUMBER () OVER (Partition By item order by entry) as rn From ItemTotal t)
    select i.item, i.size, i.entry, i.size - coalesce(o.size, 0) as difference
    from items i
    left outer join items o on o.item = i.item and o.rn = i.rn-1
    order by i.item, i.entry desc

结果输出:

item    size    entry   difference
ItemA   4487.51 2012-07-01 11:29:00.000 8.69
ItemA   4478.82 2012-07-01 11:21:00.000 0.08
ItemA   4478.74 2012-07-01 11:20:00.000 2.74
ItemA   4476.00 2012-07-01 11:15:00.000 4476.00
ItemB   1.53    2012-07-01 11:29:00.000 -0.31
ItemB   1.84    2012-07-01 11:21:00.000 0.17
ItemB   1.67    2012-07-01 11:20:00.000 -0.51
ItemB   2.18    2012-07-01 11:15:00.000 2.18

答案 1 :(得分:0)

您的数据无序。第8行早于第5-7行。我猜你想最早开始,然后从那里开始。

因此,假设表定义为:

create table ItemTotal (itemTotalId int, item varchar(10), size numeric(10,2), 
                        entry datetime, sizeDifferential numeric(10,2));

以下两次连接自身以查找相同项类型的最新上一个时间戳。因此,这忽略了rownumber,这通常是一个很好的RDBMS实践。 (我不确定它是否真的是表格的一部分,或者只是你问题中的标识符。)

update ItemTotal 
set newSize = coalesce((size - 
                  (select size 
                   from ItemTotal IT2
                   where ItemTotal.item = IT2.item
                     and IT2.entry < ItemTotal.entry
                     and not exists (select * from ItemTotal IT3
                                     where IT2.item = IT3.item
                                       and IT3.entry > IT2.entry
                                       and IT3.entry < ItemTotal.entry)
                   )
           ), size);

这种进行连接的特殊方法是找到一个前一次的行,其中不存在比选择的IT2行更新的另一行,但是小于源ItemTable行。

您也可以使用max(条目)将此最内层查询写入 - 目前尚不清楚哪个更快。

这个输出是:

    ITEM    SIZE    ENTRY                       NEWSIZE
1   ItemA   4476    July, 01 2012 11:15:00-0700 4476
2   ItemA   4478.74 July, 01 2012 11:20:00-0700 2.74
3   ItemA   4478.82 July, 01 2012 11:21:00-0700 0.08
4   ItemA   4487.51 July, 01 2012 11:29:00-0700 8.69
5   ItemB   1.53    July, 01 2012 11:29:00-0700 -0.31
6   ItemB   1.67    July, 01 2012 11:20:00-0700 -0.51
7   ItemB   1.84    July, 01 2012 11:21:00-0700 0.17
8   ItemB   2.18    July, 01 2012 11:15:00-0700 2.18

如果你直接更新这个尺寸,你显然只能运行一次。对于一次性更新,我更愿意更新到临时表/列,验证结果,然后反映回原始列。

注意:像这样的更新中的相关自联接将在几个dbs(mysql)中失败,但在大多数其他(例如MSSQL)中都有效。