我有两个表,我这样设计可能会重新考虑元素:
1. [dbo.test_db_002] with columns:
[id] = INT NOT NULL IDENTITY(1,1) PRIMARY KEY
[name] = NVARCHAR(255)
和
2. [dbo.test_db_003] with columns:
[ord] = INT
[itmid] = INT NOT NULL PRIMARY KEY
[itmid]列有一个约束,将其链接到[dbo.test_db_002]。[id]如下:
ALTER TABLE [dbo.test_db_003]
ADD CONSTRAINT fk1 FOREIGN KEY ([itmid])
REFERENCES [dbo.test_db_002]([id])
ON DELETE CASCADE ON UPDATE CASCADE;
说,[dbo.test_db_002]表格包含以下数据:
[id] [name]
3 John
5 Mary
8 Michael
10 Steve
13 Jack
20 Pete
和[dbo.test_db_003]具有以下排序数据:
[ord] [itmid]
1 5
4 8
5 13
8 3
10 10
13 20
因此,当我从数据库中检索名称时,我使用以下SQL:
SELECT [name]
FROM [dbo.test_db_002] t1
LEFT JOIN [dbo.test_db_003] t2 ON t1.[id]=t2.[itmid]
ORDER BY t2.[ord] ASC
它生成名称列表(按[dbo.test_db_003]。[ord]列排序):
Mary
Michael
Jack
John
Steve
Pete
我正在寻找的是在列表中上下移动每个名称的选项。例如,如果我想将“John”移动一个位置,我该怎么办?
到目前为止,我想出了这个部分SQL:
WITH cte AS
(
SELECT [id], [ord], ROW_NUMBER() OVER (ORDER BY t2.[ord] ASC) AS rowNum
FROM [dbo.test_db_002] t1
LEFT JOIN [dbo.test_db_003] t2 ON t1.[id] = t2.[itmid]
)
这将选择以下内容:
rowNum [id] [ord]
1 1 5
2 4 8
3 5 13
4 8 3
5 10 10
6 13 20
所以我理解我需要将[ord]列中的值从索引3开始向上移动一个(因为“John”索引是4)然后以某种方式将“John”的[ord]设置为5,但你是怎么做到的?
答案 0 :(得分:2)
我为你准备了一个complete demo如何在data.stackexchange.com上工作 该解决方案适合您的评论:
向上或向下移动只能是一步 - 换句话说,一步 不能移动2个或更多位置
在这个例子中,我让杰克在他之上做了约翰贸易顺序的位置:
WITH x AS (
SELECT t2.itmid, t2.ord
FROM dbo.test_db_002 t1
LEFT JOIN dbo.test_db_003 t2 ON (t1.id = t2.itmid)
WHERE t1.name = 'John' -- must be unique, or query by id ...
)
, y AS (
SELECT TOP 1
t.itmid, t.ord
FROM dbo.test_db_003 t, x
WHERE t.ord < x.ord -- smaller ord = "above"
ORDER BY t.ord DESC
)
UPDATE dbo.test_db_003 SET ord = z.ord
FROM (
SELECT x.itmid, y.ord FROM x,y
UNION ALL
SELECT y.itmid, x.ord FROM x,y
) z
WHERE dbo.test_db_003.itmid = z.itmid
UNION ALL
在现在简单的UPDATE
ord
必须允许传递重复项才能生效。