交换sql中一列的两个相邻行

时间:2019-10-22 07:55:23

标签: sql

我正在尝试解决以下问题:

编写一个SQL查询以交换表的一列中的两个相邻行。

输入表

Name  Id
 A    1
 B    2
 C    3
 D    4
 E    5

输出表

Name  Id
 A    2
 B    1
 C    4
 D    3
 E    5

描述:-1与A关联,2与B关联,交换它们,因此现在1与B关联,2与A关联,对于C和D同样如此,由于E没有任何对,因此将其保留为是的。

注意:-这可以使用CASE语句解决,但我正在尝试一种通用解决方案,说目前只有5行,可能是10,20等。

例如:

SELECT
*,CASE WHEN Name = A then 2 ELSEIF Name = B then 1 etc...
FROM YourTable

3 个答案:

答案 0 :(得分:1)

您可以使用窗口函数来解决此问题。

在MySQL(> = 8.0)上:

SELECT ID, IFNULL(CASE WHEN t.rn % 2 = 0 THEN LAG(Name) OVER (ORDER BY ID) ELSE LEAD(Name) OVER (ORDER BY ID) END, Name) AS Name
FROM (
  SELECT ID, Name, ROW_NUMBER() OVER (ORDER BY ID) AS rn 
  FROM table_name
) t

demo on dbfiddle.uk

在SQL Server上:

SELECT ID, ISNULL(CASE WHEN t.rn % 2 = 0 THEN LAG(Name) OVER (ORDER BY ID) ELSE LEAD(Name) OVER (ORDER BY ID) END, Name) AS Name
FROM (
  SELECT ID, Name, ROW_NUMBER() OVER (ORDER BY ID) AS rn 
  FROM table_name
) t

demo on dbfiddle.uk

答案 1 :(得分:1)

如果您有sql-server,可以尝试一下。

DECLARE @YourTable TABLE (Name VARCHAR(10), Id INT)
INSERT INTO @YourTable VALUES
 ('A', 1),
 ('B', 2),
 ('C', 3),
 ('D', 4),
 ('E', 5)


;WITH CTE AS ( 
    SELECT *, ROW_NUMBER()OVER(ORDER BY Name) AS RN FROM @YourTable
 )
SELECT T1.Name, ISNULL(T2.Id, T1.Id) Id  FROM CTE T1 
    LEFT JOIN CTE T2 ON T1.RN + CASE WHEN T1.RN%2 = 0 THEN - 1 ELSE 1 END  = T2.RN 

结果:

Name       Id
---------- -----------
A          2
B          1
C          4
D          3
E          5

答案 2 :(得分:0)

您没有指定DBMS,但是以下是标准的ANSI SQL。

您可以使用values()子句来提供ID的映射,然后加入该映射:

with id_map (source_id, target_id) as ( 
  values
     (1, 2),
     (2, 1) 
)
select t.name, coalesce(m.target_id, t.id) as mapped_id
from the_table t
   left join id_map m on m.source_id = t.id
order by name;

或者,如果您只想为一个方向指定一次映射,则可以使用以下方法:

with id_map (source_id, target_id) as ( 
  values
     (1, 2) 
)
select t.name,
       case id 
          when m.source_id then m.target_id
          when m.target_id then m.source_id
          else id
       end as mapped_id
from the_table t
   left join id_map m on t.id in (m.source_id, m.target_id)
order by name;

在线示例:enter image description here