我想知道基于另一行更新行的最佳方法是什么,比方说我有这样的表:
ID | NAME | VALUE |
----------------------------
1 | a | 10 |
2 | b | NULL |
3 | c | NULL |
4 | d | NULL |
5 | a | 10 |
6 | b | NULL |
7 | c | NULL |
8 | d | NULL |
9 | a | NULL |
.
.
.
现在我需要一个UPDATE查询,将所有名称= d的行与name = a的行进行比较,如果name = a的行的值= 10,则name = d的行将得到value = 10然后使用name = a的行将设置为NULL,否则将设置为NULL。就像我需要按顺序在行的值(a到d,b到c,c到d,d到a)之间切换。在每4行(a,b,c,d)中,总共只有一行,该值不为空。
我希望很清楚。 谢谢!
答案 0 :(得分:1)
我认为我并不完全理解你在这里想要达到的目标,但是这里有一些事情要开始讨论:
--Create sample data
IF OBJECT_ID('tempdb..#temp') IS NOT NULL
DROP TABLE #temp;
CREATE TABLE #temp (ID INT, NAME VARCHAR(50), [VALUE] INT);
INSERT INTO #temp SELECT 1, 'a', 10;
INSERT INTO #temp SELECT 2, 'b', NULL;
INSERT INTO #temp SELECT 3, 'c', NULL;
INSERT INTO #temp SELECT 4, 'd', NULL;
INSERT INTO #temp SELECT 5, 'a', 10;
INSERT INTO #temp SELECT 6, 'b', NULL;
INSERT INTO #temp SELECT 7, 'c', NULL;
INSERT INTO #temp SELECT 8, 'd', NULL;
INSERT INTO #temp SELECT 9, 'a', NULL;
所有这一切都是为了交换a和d,如果a中有值:
WITH Best AS (
SELECT NAME, MAX([VALUE]) AS MAXVALUE FROM #temp GROUP BY NAME)
UPDATE
t
SET
[VALUE] =
CASE
WHEN t.NAME = 'a' AND b.MAXVALUE IS NOT NULL THEN NULL
WHEN t.NAME = 'd' AND b.MAXVALUE IS NOT NULL THEN b.MAXVALUE
END
FROM
#temp t
CROSS JOIN Best b
WHERE
t.NAME IN ('a', 'd')
AND b.NAME = 'a';
SELECT * FROM #temp;
完成后,我可以看到所有值都已移至d行。但这并不能解决b到c,c到d等问题。这有点像你想要的吗?
现在看起来你实际上需要分别处理每组四行,所以这可能会更好吗?
WITH Groups AS (
SELECT ID, (ID - 1) / 4 AS group_id, NAME, [VALUE] FROM #temp),
Best AS (
SELECT group_id, NAME, MAX([VALUE]) AS MAXVALUE FROM Groups GROUP BY group_id, NAME)
UPDATE
t
SET
[VALUE] =
CASE
WHEN t.NAME = 'a' AND b.MAXVALUE IS NOT NULL THEN NULL
WHEN t.NAME = 'd' AND b.MAXVALUE IS NOT NULL THEN b.MAXVALUE
END
FROM
#temp t
INNER JOIN Groups g ON g.ID = t.ID
INNER JOIN Best b ON b.group_id = g.group_id
WHERE
t.NAME IN ('a', 'd')
AND b.NAME = 'a';
这是给你的一个新查询,现在我终于想到我明白应该做什么了。首先,这是我对你真正想要的东西的理解:
我创建了一组略有不同的数据,以显示这在实践中有效:
--Create sample data
IF OBJECT_ID('tempdb..#temp') IS NOT NULL
DROP TABLE #temp;
CREATE TABLE #temp (ID INT, NAME VARCHAR(50), [VALUE] INT);
INSERT INTO #temp SELECT 1, 'a', 10;
INSERT INTO #temp SELECT 2, 'b', NULL;
INSERT INTO #temp SELECT 3, 'c', NULL;
INSERT INTO #temp SELECT 4, 'd', NULL;
INSERT INTO #temp SELECT 5, 'a', NULL;
INSERT INTO #temp SELECT 6, 'b', NULL;
INSERT INTO #temp SELECT 7, 'c', NULL;
INSERT INTO #temp SELECT 8, 'd', 5;
INSERT INTO #temp SELECT 9, 'a', NULL;
INSERT INTO #temp SELECT 10, 'b', 90;
INSERT INTO #temp SELECT 11, 'c', NULL;
INSERT INTO #temp SELECT 12, 'd', NULL;
...这是我修改过的查询:
WITH Groups AS (
SELECT
(ID - 1) / 4 AS group_id,
ID,
NAME,
[VALUE]
FROM
#temp),
Best AS (
SELECT
group_id,
ID,
NAME,
[VALUE]
FROM
Groups
WHERE
[VALUE] IS NOT NULL)
UPDATE
t
SET
[VALUE] =
CASE
WHEN t.NAME = 'a' AND b.NAME = 'a' THEN NULL
WHEN t.NAME = 'a' AND b.NAME = 'd' THEN b.[VALUE]
WHEN t.NAME = 'b' AND b.NAME = 'b' THEN NULL
WHEN t.NAME = 'b' AND b.NAME = 'a' THEN b.[VALUE]
WHEN t.NAME = 'c' AND b.NAME = 'c' THEN NULL
WHEN t.NAME = 'c' AND b.NAME = 'b' THEN b.[VALUE]
WHEN t.NAME = 'd' AND b.NAME = 'd' THEN NULL
WHEN t.NAME = 'd' AND b.NAME = 'c' THEN b.[VALUE]
END
FROM
#temp t
INNER JOIN Groups g ON g.ID = t.ID
INNER JOIN Best b ON b.group_id = g.group_id;
所以我的数据就像这样开始:
ID NAME VALUE
1 a 10
2 b NULL
3 c NULL
4 d NULL
5 a NULL
6 b NULL
7 c NULL
8 d 5
9 a NULL
10 b 90
11 c NULL
12 d NULL
...当我运行UPDATE查询时:
ID NAME VALUE
1 a NULL
2 b 10
3 c NULL
4 d NULL
5 a 5
6 b NULL
7 c NULL
8 d NULL
9 a NULL
10 b NULL
11 c 90
12 d NULL
如果我再次运行查询,那么一切都会再移动一步:
ID NAME VALUE
1 a NULL
2 b NULL
3 c 10
4 d NULL
5 a NULL
6 b 5
7 c NULL
8 d NULL
9 a NULL
10 b NULL
11 c NULL
12 d 90
如果这仍然不是您想要的,那么要么在第一次/第二次迭代后显示您认为值应该是什么,要么在之前提出一个新的 - >以你的问题为例。
希望这将是最后的尝试:D
WITH Groups AS (
SELECT
(ID - 1) / 4 AS group_id,
ID,
NAME,
[VALUE]
FROM
#temp),
Best AS (
SELECT
group_id,
ID,
NAME,
[VALUE]
FROM
Groups
WHERE
[VALUE] IS NOT NULL)
UPDATE
t
SET
[VALUE] =
CASE
--a to d
WHEN t.NAME = 'd' AND b.NAME = 'a' THEN b.[VALUE]
--b to c
WHEN t.NAME = 'c' AND b.NAME = 'b' THEN b.[VALUE]
--c to d (seems wrong?)
WHEN t.NAME = 'd' AND b.NAME = 'c' THEN b.[VALUE]
--d to a
WHEN t.NAME = 'a' AND b.NAME = 'd' THEN b.[VALUE]
--Set the moving item to NULL
WHEN t.NAME = b.NAME THEN NULL
END
FROM
#temp t
INNER JOIN Groups g ON g.ID = t.ID
INNER JOIN Best b ON b.group_id = g.group_id;