如何将每2行转换为1行?

时间:2016-08-18 07:15:02

标签: sql sql-server sql-server-2014

我有以下表格:

CREATE TABLE source_table (
    id int IDENTITY(1, 1) NOT NULL,
    category varchar(255) NULL,
    item int NULL,
    counter int NULL,
    length int NULL
);

CREATE TABLE dest_table(
    id int IDENTITY(1, 1) NOT NULL,
    from_item [int] NULL,
    to_item [int] NULL,
    length [int] NULL
);

源表包含以下记录:

INSERT INTO source_table SELECT 'A', 100, 1, 0
INSERT INTO source_table SELECT 'A', 101, 2, 10
INSERT INTO source_table SELECT 'A', 102, 3, 5
INSERT INTO source_table SELECT 'A', 103, 4, 7
INSERT INTO source_table SELECT 'A', 104, 5, 12
INSERT INTO source_table SELECT 'B', 101, 1, 0
INSERT INTO source_table SELECT 'B', 111, 2, 15
INSERT INTO source_table SELECT 'B', 114, 3, 6
INSERT INTO source_table SELECT 'B', 117, 4, 13
INSERT INTO source_table SELECT 'B', 119, 5, 8

源表中的行需要以这样的方式进行转换,以便目标表中的每条记录代表源表中的2行。

在目标表中将上述行转换为以下内容的正确SQL语法是什么?

100, 101, 10
101, 102, 5
102, 103, 7
103, 104, 12
101, 111, 15
111, 114, 6
114, 117, 13
117, 119, 8

4 个答案:

答案 0 :(得分:1)

您可以使用lag窗口函数:

select *
from   (select lag(item) over (partition by category order by item) as from_item,
               item as to_item,
               length
        from   source_table) base
where   from_item is not null

将其插入目标表是标准的。

答案 1 :(得分:0)

执行SELF JOIN

<强>查询

insert into dest_table([from_item], [to_item], [length])
select t.* from(
    select t1.[item] as col_1, t2.[item] as col_2, t2.[length]
    from source_table t1
    join source_table t2
    on t1.id = t2.id -1
)t
where t.[length] <> 0;

结果集如下所示。

+-----+-----+------+
|col_1|col_2|length|
+-----+-----+------+
| 100 | 101 | 10   |
| 101 | 102 | 5    |
| 102 | 103 | 7    |
| 103 | 104 | 12   |
| 101 | 111 | 15   |
| 111 | 114 | 6    |
| 114 | 117 | 13   |
| 117 | 119 | 8    |
+-----+-----+------+

修改

如果标识列中存在间隙。然后,

<强>查询

;with cte as(
    select rn = row_number() over(
        order by id
    ), *
    from source_table
)
insert into dest_table([from_item], [to_item], [length])
select t.* from(
    select t1.[item] as col_1, t2.[item] as col_2, t2.[length]
    from cte t1
    join cte t2
    on t1.id = t2.id -1
)t
where t.[length] <> 0;

答案 2 :(得分:0)

SELECT a.item, b.item, b.length
FROM source_table as a
INNER JOIN source_table b
  ON a.id = b.id - 1
  AND a.category = b.category

答案 3 :(得分:0)

如果该计数器没有间隙,那么您可以对该类别和类别进行自我加入。

例如:

DECLARE @source_table TABLE (
    id int IDENTITY(1, 1) NOT NULL,
    category varchar(1) NULL,
    item int NULL,
    [counter] int NULL,
    [length] int NULL
);

DECLARE @dest_table TABLE(
    id int IDENTITY(1, 1) NOT NULL,
    category varchar(1) NULL,
    from_item int NULL,
    to_item int NULL,
    [length] int NULL
);

INSERT INTO @source_table (category, item, [counter], [length]) values 
('A', 100, 1, 0),
('A', 101, 2, 10),
('A', 102, 3, 5),
('A', 103, 4, 7),
('A', 104, 5, 12),
('B', 101, 1, 0),
('B', 111, 2, 15),
('B', 114, 3, 6),
('B', 117, 4, 13),
('B', 119, 5, 8);

insert into @dest_table (category, from_item, to_item, [length])
select t1.category,  t1.item, t2.item, t2.[length]
from @source_table t1
join @source_table t2 
  on (t1.category = t2.category and t1.[counter]+1 = t2.[counter]);

select * from @dest_table;

如果Id或计数器之间存在间隙,则row_number可用于使用相同的方法 例如:

with SRC AS (
 select category, item, [length],
 row_number() over (partition by category order by id) as [counter] 
 from @source_table
)
insert into @dest_table (category, from_item, to_item, [length])
select t1.category,  t1.item, t2.item, t2.[length]
from SRC t1
join SRC t2
  on (t1.category = t2.category and t1.[counter]+1 = t2.[counter]);