SQL 服务器如何使用 SELECT 和 GROUP BY 子句进行更新
SQL Server How to UPDATE with SELECT and GROUP BY clause
我们的团队使用 SQL 服务器,我想使用聚合函数为正在插入的新值更新其中一列,现有 table。
下面是现有的 table 和其中的值。
CREATE TABLE CARS
(
ID INT NOT NULL,
carCompany VARCHAR(100) NOT NULL,
feature VARCHAR(100) NOT NULL,
sequence INT NOT NULL
);
INSERT INTO CARS VALUES (1, 'Toyota', 'Auto transmission', 1);
INSERT INTO CARS VALUES (2, 'BMW', 'Keyless Entry system', 1);
INSERT INTO CARS VALUES (3, 'Toyota', 'Power Steering', 2);
INSERT INTO CARS VALUES (4, 'Tesla', 'Auto transmission', 1);
INSERT INTO CARS VALUES (5, 'BMW', 'Auto transmission', 2);
INSERT INTO CARS VALUES (6, 'Tesla', 'Keyless Entry system', 2);
INSERT INTO CARS VALUES (7, 'BMW', 'Power Steering', 3);
对于 BMW 和 Tesla 的 'Auto Pilot' 要求仅在同一个 carCompany 组中递增序列列。由于 Insert 语句更容易,我只是插入记录并努力使 Update 语句正确。
INSERT INTO CARS VALUES (8, 'Tesla', 'Auto Pilot', 0);
INSERT INTO CARS VALUES (9, 'BMW', 'Auto Pilot', 0);
以下 UPDATE
语句不正确。请在这里帮忙。
UPDATE c1
SET c1.sequence = d.sq
FROM
(SELECT MAX(c2.sequence) + 1 AS sq
FROM CARS c2
WHERE c2.carCompany = c1.carCompany
GROUP BY c2.carCompany) d
WHERE c1.sequence = 0
大功告成,只需将相关子查询移动到 SET 语句中即可:
UPDATE c1
SET c1.sequence = (SELECT max(fc2.sequence) + 1 as sq FROM CARS c2 WHERE c2.carCompany = c1.carCompany GROUP BY c2.carCompany)
FROM CARS c1
WHERE c1.sequence = 0
但请注意,这仅适用于该汽车公司只有一项新记录的情况。即,如果您有两个新的 Tesla 功能,它们都将设置为 2。您可以使用带有 RANK 函数的 CTE 来允许任意数量的新值:
WITH NewSequences
AS (
SELECT id, RANK()OVER(PARTITION BY c1.carCompany ORDER BY id) + (SELECT max(fc2.sequence) + 1 as sq FROM CARS c2 WHERE c2.carCompany = c1.carCompany GROUP BY c2.carCompany) AS NewSeq
FROM CARS
WHERE c1.[sequence] = 0
)
UPDATE c1
SET c1.sequence = n.NewSeq
FROM CARS c1
INNER JOIN NewSequences n
ON c1.id = NewSequences.id
如果您只想要下一个序列号,您的查询就非常接近了:
UPDATE cars
SET sequence = d.sq
FROM (SELECT max(c2.sequence) + 1 as sq
FROM CARS c2
GROUP BY c2.carCompany
) c2
ON c2.carCompany = c1.carCompany
WHERE sequence = 0;
注意:如果您插入了同一家公司的多行,我认为这不会满足您的要求。据推测,您希望它们具有不同的值,因此您可以使用:
with toupdate as (
select c.*,
max(c.sequence) over (partition by carcompany) as max_sequence,
row_number() over (partition by carcompany order by id) as seqnum
from cars c
)
update toupdate
set sequence = max_sequence + seqnum
where sequence = 0;
然而,当你可以使用时,预先计算这个值似乎是完全没有必要的:
select c.*,
row_number() over (partition by carCompany order by id) as seq
from cars c;
我没有理由存储这个值。
我们的团队使用 SQL 服务器,我想使用聚合函数为正在插入的新值更新其中一列,现有 table。
下面是现有的 table 和其中的值。
CREATE TABLE CARS
(
ID INT NOT NULL,
carCompany VARCHAR(100) NOT NULL,
feature VARCHAR(100) NOT NULL,
sequence INT NOT NULL
);
INSERT INTO CARS VALUES (1, 'Toyota', 'Auto transmission', 1);
INSERT INTO CARS VALUES (2, 'BMW', 'Keyless Entry system', 1);
INSERT INTO CARS VALUES (3, 'Toyota', 'Power Steering', 2);
INSERT INTO CARS VALUES (4, 'Tesla', 'Auto transmission', 1);
INSERT INTO CARS VALUES (5, 'BMW', 'Auto transmission', 2);
INSERT INTO CARS VALUES (6, 'Tesla', 'Keyless Entry system', 2);
INSERT INTO CARS VALUES (7, 'BMW', 'Power Steering', 3);
对于 BMW 和 Tesla 的 'Auto Pilot' 要求仅在同一个 carCompany 组中递增序列列。由于 Insert 语句更容易,我只是插入记录并努力使 Update 语句正确。
INSERT INTO CARS VALUES (8, 'Tesla', 'Auto Pilot', 0);
INSERT INTO CARS VALUES (9, 'BMW', 'Auto Pilot', 0);
以下 UPDATE
语句不正确。请在这里帮忙。
UPDATE c1
SET c1.sequence = d.sq
FROM
(SELECT MAX(c2.sequence) + 1 AS sq
FROM CARS c2
WHERE c2.carCompany = c1.carCompany
GROUP BY c2.carCompany) d
WHERE c1.sequence = 0
大功告成,只需将相关子查询移动到 SET 语句中即可:
UPDATE c1
SET c1.sequence = (SELECT max(fc2.sequence) + 1 as sq FROM CARS c2 WHERE c2.carCompany = c1.carCompany GROUP BY c2.carCompany)
FROM CARS c1
WHERE c1.sequence = 0
但请注意,这仅适用于该汽车公司只有一项新记录的情况。即,如果您有两个新的 Tesla 功能,它们都将设置为 2。您可以使用带有 RANK 函数的 CTE 来允许任意数量的新值:
WITH NewSequences
AS (
SELECT id, RANK()OVER(PARTITION BY c1.carCompany ORDER BY id) + (SELECT max(fc2.sequence) + 1 as sq FROM CARS c2 WHERE c2.carCompany = c1.carCompany GROUP BY c2.carCompany) AS NewSeq
FROM CARS
WHERE c1.[sequence] = 0
)
UPDATE c1
SET c1.sequence = n.NewSeq
FROM CARS c1
INNER JOIN NewSequences n
ON c1.id = NewSequences.id
如果您只想要下一个序列号,您的查询就非常接近了:
UPDATE cars
SET sequence = d.sq
FROM (SELECT max(c2.sequence) + 1 as sq
FROM CARS c2
GROUP BY c2.carCompany
) c2
ON c2.carCompany = c1.carCompany
WHERE sequence = 0;
注意:如果您插入了同一家公司的多行,我认为这不会满足您的要求。据推测,您希望它们具有不同的值,因此您可以使用:
with toupdate as (
select c.*,
max(c.sequence) over (partition by carcompany) as max_sequence,
row_number() over (partition by carcompany order by id) as seqnum
from cars c
)
update toupdate
set sequence = max_sequence + seqnum
where sequence = 0;
然而,当你可以使用时,预先计算这个值似乎是完全没有必要的:
select c.*,
row_number() over (partition by carCompany order by id) as seq
from cars c;
我没有理由存储这个值。