2016-08-18 78 views
-1

我有以下表格:如何將每2行轉換爲1行?

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 
+2

結果集中的最後一行如何成爲'119,5,8'?以及117,\t 119,\t 8'錯過了? – Wanderer

+0

@烏拉斯我的壞。修正了錯字! –

+0

@MartinSmith MS SQL Server 2014 –

回答

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; 
+1

SQL Server不保證身份沒有差距。 –

+0

然後我們可以使用row_number選項。 – Wanderer

+0

如果某個類別的第一個長度不是0,該怎麼辦? – Petaflop

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

我想他們可能需要'ORDER BY項目'雖然問題是不清楚,有三種可能性。 –

+0

@MartinSmith,爲true,但最終排序順序與目標僅在另一個表中插入記錄時無關。 – trincot

+0

不適用於排序順序,但在滯後的定義中。來自和來自項目列名稱暗示,這應該按項目而不是按櫃檯排序。 –

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 
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]);