SQL通过翻转将2列向下移动
Posted
技术标签:
【中文标题】SQL通过翻转将2列向下移动【英文标题】:SQL Shifting 2 columns a row down with rollover 【发布时间】:2020-10-14 23:23:45 【问题描述】:我目前正在尝试在 SQL Server 中操作一个表。
下表是一个例子:
Id | PrimaryId | PrimaryMail | SecondaryId | SecondaryMail
1. 1. email1@something. 5. email2@something
2. 2. email3@something. 6. email4@something
3. 3. email5@something. 7. email6@something
4. 4. email7@something. 8. email8@something
我希望它变成如下:
Id | PrimaryId | PrimaryMail | SecondaryId | SecondaryMail
1. 1. email1@something. 6. email4@something
2. 2. email3@something. 7. email6@something
3. 3. email5@something. 8. email8@something
4. 4. email7@something. 5. email2@something
我在这里发现了一个类似的问题,但这个人不想使用连接,而我真正想要的是翻转机制,它使第一行成为最后一行或最后一行成为第一行,具体取决于什么移动列的方向。
我已经有了以下代码,可以使列中的项目增加 1 行。但是最后一行目前保持不变,我丢失了第一行的数据。
--Calculate the height of the table
DECLARE @CouplesCount AS INT
SELECT @CouplesCount = COUNT(*) FROM Couples
--Shift the Secondary users down one row
UPDATE c1
SET c1.SecondaryId = c2.SecondaryId, c1.SecondaryMail = c2.SecondaryMail
FROM Couples c1 join
Couples c2
on c2.Id = c1.Id + 1
WHERE c1.CouplesId <= @CouplesCount - 1
SELECT * FROM Couples
提前感谢任何可以帮助我的人。 p.s.我不能使用 mysql 代码
【问题讨论】:
如果表格多于两行,你要哪种逻辑呢?如果您可以用更多的行来扩展您的数据和结果,这可能会有所帮助。 我编辑了行数。我基本上希望它循环播放。 【参考方案1】:如果您使用的 SQL Server 版本是 SQL Server 2012 或更高版本,则可以使用窗口函数LEAD
和FIRST_VALUE
。
LEAD
从“下一个”行返回值(由ORDER BY
子句定义)。它将为最后一行返回NULL
,因为那里没有“下一个”行。
所以,对于最后一行我们需要返回第一行,这可以通过FIRST_VALUE
来完成。
样本数据
DECLARE @Couples TABLE (
Id int, PrimaryId int, PrimaryMail nvarchar(100),
SecondaryId int, SecondaryMail nvarchar(100));
INSERT INTO @Couples VALUES
(1, 1, 'email1@something', 5, 'email2@something'),
(2, 2, 'email3@something', 6, 'email4@something'),
(3, 3, 'email5@something', 7, 'email6@something'),
(4, 4, 'email7@something', 8, 'email8@something');
查询
SELECT
C.Id
,C.PrimaryId
,C.PrimaryMail
,ISNULL(LEAD(C.SecondaryId) OVER (ORDER BY C.Id),
FIRST_VALUE(C.SecondaryId) OVER (ORDER BY C.Id))
AS SecondaryId
,ISNULL(LEAD(C.SecondaryMail) OVER (ORDER BY C.Id),
FIRST_VALUE(C.SecondaryMail) OVER (ORDER BY C.Id))
AS SecondaryMail
FROM
@Couples AS C
;
结果
+----+-----------+------------------+-------------+------------------+
| Id | PrimaryId | PrimaryMail | SecondaryId | SecondaryMail |
+----+-----------+------------------+-------------+------------------+
| 1 | 1 | email1@something | 6 | email4@something |
| 2 | 2 | email3@something | 7 | email6@something |
| 3 | 3 | email5@something | 8 | email8@something |
| 4 | 4 | email7@something | 5 | email2@something |
+----+-----------+------------------+-------------+------------------+
更新
如果您需要实际更改表本身,也很容易做到,只需将查询包装在 CTE 中并更新即可。
WITH
CTE
AS
(
SELECT
C.Id
,C.PrimaryId
,C.PrimaryMail
,C.SecondaryId
,C.SecondaryMail
,ISNULL(LEAD(C.SecondaryId) OVER (ORDER BY C.Id),
FIRST_VALUE(C.SecondaryId) OVER (ORDER BY C.Id))
AS NewSecondaryId
,ISNULL(LEAD(C.SecondaryMail) OVER (ORDER BY C.Id),
FIRST_VALUE(C.SecondaryMail) OVER (ORDER BY C.Id))
AS NewSecondaryMail
FROM
@Couples AS C
)
UPDATE CTE
SET
SecondaryId = NewSecondaryId
,SecondaryMail = NewSecondaryMail
;
SELECT * FROM @Couples ORDER BY Id;
【讨论】:
非常感谢@Vladimir Baranov 的回答!可悲的是,我的水平仍然很低,以至于您看不到我的赞成票。 如果您觉得这个答案有用,您应该可以接受。获得足够的声望来投票应该很容易。您只需要 15 个。只需为某人的问题写一个好的答案并获得支持。或者对其他问题提出一些好的修改建议。以上是关于SQL通过翻转将2列向下移动的主要内容,如果未能解决你的问题,请参考以下文章
R方法通过将整个数据集向上移动一个小时/向下移动一个小时半年来将标准转换为夏令时?
pandas使用shift函数对数数据进行向上偏移(-1)或者向下偏移索引不移动,移动之后无值的赋值为NaN将原数据列与偏移后的数据列相加生成新的数据列