基于SQL中的下一个和上一个记录进行排序

Nic*_* N. 6 sql sql-server sql-server-2005

我试图通过考虑下一个和以前的记录来订购特定的查询,但我似乎无法完成它.我想通过数字和字母来订购,但是,例如,如果数字1的最后一个字母等于数字2中的一个字母,我想更改顺序,以便该字母与以下字母匹配记录.

Create script and SQL fiddle demo

create table Parent (
id [bigint] IDENTITY(1,1), 
number bigint NOT NULL,
PRIMARY KEY (id)
)
GO

create table Child (
id [bigint] IDENTITY(1,1), 
parentId BIGINT, 
letter VARCHAR(1) NOT NULL,
PRIMARY KEY (id),
UNIQUE (parentId, Letter),
FOREIGN KEY (parentId) REFERENCES Parent(id)
)
GO

INSERT Parent (number) VALUES (1)
INSERT Parent (number) VALUES (2)
INSERT Parent (number) VALUES (3)

INSERT Child (parentId, letter) VALUES (1, 'A')
INSERT Child (parentId, letter) VALUES (1, 'C')
INSERT Child (parentId, letter) VALUES (2, 'B')
INSERT Child (parentId, letter) VALUES (2, 'C')
INSERT Child (parentId, letter) VALUES (3, 'B')
INSERT Child (parentId, letter) VALUES (3, 'D')
Run Code Online (Sandbox Code Playgroud)

当前查询

目前我正在使用此查询进行排序:

SELECT P.number, C.letter 
FROM Child C
JOIN Parent P ON C.parentId = P.id
ORDER BY P.number, C.letter
Run Code Online (Sandbox Code Playgroud)

当前结果集

number               letter
-------------------- ------
1                    A
1                    C
2                    B
2                    C
3                    B
3                    D
Run Code Online (Sandbox Code Playgroud)

预期结果集

为了澄清我实际想做的事情,这里是预期的结果集(切换了2号的C和B).

number               letter
-------------------- ------
1                    A
1                    C
2                    C --switched
2                    B --switched
3                    B
3                    D
Run Code Online (Sandbox Code Playgroud)

其他要求和问题

  • 它必须在SQL SERVER 2005中工作.
  • 有一个场景,每个号码使用3个字母,如果它只使用最佳匹配,我很高兴.
  • 我实际上也对SQL Server的更高版本(用于学习)的解决方案感兴趣,但那些不回答我的问题.

任何人都可以指出我正确的方向如何做到这一点?

ugh*_*hai 6

你可以做这样的事情.

  1. 使用ROW_NUMBER()和标识每个父母的第一个和最后一个字母PARTITION BY
  2. 将前id一个记录与下一个记录匹配id.
  3. 检查第二个父ID是否有任何与上面选择的字母匹配的字母
  4. 使用LEFT JOIN和使用CASEISNULLid字母匹配的记录设置更高的优先级

询问

;WITH CTE AS 
(
SELECT id,ParentID,letter,
ROW_NUMBER()OVER(PARTITION BY parentId ORDER BY ID) first_element,
ROW_NUMBER()OVER(PARTITION BY parentId ORDER BY ID DESC) Last_element
FROM Child
), CTE2 AS 
(
SELECT c1.id,c1.parentid,c1.letter,c2.parentid as c2parentid
FROM CTE c1
INNER JOIN CTE c2
ON c1.last_element = 1
AND c2.first_element = 1
AND c1.id +1 = c2.id
), CTE3 AS 
(
SELECT C.parentid,C.id
FROM CTE2
INNER JOIN child C ON CTE2.c2parentid = C.parentid
AND C.letter = CTE2.letter
)
SELECT P.number, C.letter
FROM Child C
JOIN Parent P ON C.parentId = P.id
LEFT JOIN CTE3 ON CTE3.id = C.id
ORDER BY P.number, ISNULL(CTE3.id,0) DESC, C.letter 
Run Code Online (Sandbox Code Playgroud)

产量

number  letter
1   A
1   C
2   C
2   B
3   B
3   D
Run Code Online (Sandbox Code Playgroud)

SQL小提琴

编辑

如果你ids不是顺序的,你可以改变CTE1CTE2喜欢这个来利用ROW_NUMBER()OVER(ORDER BY ID) seq_id.

;WITH CTE AS 
(
SELECT id,ParentID,letter,
ROW_NUMBER()OVER(ORDER BY ID) seq_id,
ROW_NUMBER()OVER(PARTITION BY parentId ORDER BY ID) first_element,
ROW_NUMBER()OVER(PARTITION BY parentId ORDER BY ID DESC) Last_element
FROM Child
), CTE2 AS 
(
SELECT c1.id,c1.parentid,c1.letter,c2.parentid as c2parentid
FROM CTE c1
INNER JOIN CTE c2
ON c1.last_element = 1
AND c2.first_element = 1
AND c1.seq_id + 1 = c2.seq_id
)
Run Code Online (Sandbox Code Playgroud)

其余代码保持不变.

SQL小提琴