帮助SQL - 将两行合并为一行

时间:2009-09-01 22:49:10

标签: sql sql-server-2005 pivot

我有一个有趣的SQL问题需要帮助。

以下是样本数据集:

Warehouse  DateStamp   TimeStamp  ItemNumber  ID
    A       8/1/2009    10001         abc      1
    B       8/1/2009    10002         abc      1 
    A       8/3/2009    12144         qrs      5
    C       8/3/2009    12143         qrs      5
    D       8/5/2009    6754          xyz      6
    B       8/5/2009    6755          xyz      6

此数据集表示两个仓库之间的库存转移。有两个记录代表每次传输,这两个传输记录总是具有相同的ItemNumber,DateStamp和ID。两个传输记录的TimeStamp值总是相差1,其中较小的TimeStamp表示源仓库记录,较大的TimeStamp表示目标仓库记录。

使用上面的示例数据集,这是我需要的查询结果集:

Warehouse_Source  Warehouse_Destination  ItemNumber  DateStamp
    A                B                      abc       8/1/2009
    C                A                      qrs       8/3/2009
    D                B                      xyz       8/5/2009   

我可以编写代码来生成所需的结果集,但我想知道这个记录组合是否可以通过SQL实现。我使用SQL Server 2005作为我的底层数据库。我还需要在SQL中添加一个WHERE子句,例如,我可以在Warehouse_Source = A上搜索。不,我无法更改数据模型;)。

非常感谢任何建议!

此致 标记

2 个答案:

答案 0 :(得分:7)

SELECT source.Warehouse as Warehouse_Source 
, dest.Warehouse as Warehouse_Destination
, source.ItemNumber
, source.DateStamp
FROM table source
JOIN table dest ON source.ID = dest.ID 
  AND source.ItemNumber = dest.ItemNumber
  AND source.DateStamp = dest.DateStamp
  AND source.TimeStamp = dest.TimeStamp + 1

答案 1 :(得分:0)

标记,

以下是使用row_number和PIVOT执行此操作的方法。根据我的建议,使用列上的聚簇索引或主键,它将使用没有排序操作的直线查询计划,因此效率非常高。

create table T(
  Warehouse char,
  DateStamp datetime,
  TimeStamp int,
  ItemNumber varchar(10),
  ID int,
  primary key(ItemNumber,DateStamp,ID,TimeStamp)
);
insert into T values ('A','20090801','10001','abc','1');
insert into T values ('B','20090801','10002','abc','1'); 
insert into T values ('A','20090803','12144','qrs','5');
insert into T values ('C','20090803','12143','qrs','5');
insert into T values ('D','20090805','6754','xyz','6');
insert into T values ('B','20090805','6755','xyz','6');

with Tpaired(Warehouse,DateStamp,TimeStamp,ItemNumber,ID,rk) as (
  select
    Warehouse,DateStamp,TimeStamp,ItemNumber,ID,
    row_number() over (
      partition by ItemNumber,DateStamp,ID
      order by TimeStamp
    )
  from T
)
  select
    max([1]) as Warehouse_Source,
    max([2]) as Warehouse_Destination,
    ItemNumber,
    DateStamp
  from Tpaired
  pivot (
    max(Warehouse) for rk in ([1],[2])
  ) as P
  group by ItemNumber, DateStamp, ID;
go

drop table T;