sql:如果两行id重复,只保留最小值
sql: keep only the minimum value if two rows have duplicate id
下面是我的示例数据。第 3 行和第 4 行具有相同的 st_case(主键),但它们的 dist_min 不同。我想保留具有最小 dist_min 值的行。请注意,可能有 2 个以上的重复行与相同的 st_case 相关联。非常感谢您的帮助!
在 MySQL 中,您可以使用 delete
和 join
:
delete s
from sample s left join
(select st_case, min(dist_min) as mindm
from sample s
group by st_case
) ss
on ss.st_case = s.st_case and s.dist_min > ss.mindm;
我没有测试这个所以请原谅任何语法错误。 SQL ranking functions 可以解决你的问题。本质上,您按一列分组,然后按另一列排名。那你就可以select只有排名第一的
SELECT *
FROM(
SELECT *, Rank() OVER (PARTITION BY 'st_case' Order by Dist_min DESC) as Rank
From 'tbl_Name')
WHERE Rank = '1'
DELETE FROM sample
WHERE dist_min !=(SELECT dist_min FROM (SELECT * FROM sample) sample2
WHERE sample2.st_case = sample.st_case
ORDER BY dist_min
LIMIT 1)
正如 SAM M 所建议的,我不确定您如何拥有具有相同主键的重复行。
但是,如果 st_case 不是您唯一的键,而 table 有一个复合键
或者如果它是一个非关键列,
你可以写一个触发器来控制插入
类似于:
CREATE table CALC_STATUS(id varchar(40), correlatoinToken integer, requirement double)
CREATE TRIGGER keep_min BEFORE INSERT ON CALC_STATUS
FOR EACH row
BEGIN
IF NEW.correlatoinToken = correlatoinToken AND NEW.requirement <= requirement then
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = "A row with similar correlation token with lower requirement already exists";
ELSEIF NEW.correlatoinToken = correlatoinToken AND NEW.requirement > requirement
NEW.requirement = requirement;
END IF;
END;
如果你想查询:
SELECT c1.* FROM CALC_STATUS c1,(SELECT st_case,MIN(dist_min) FROM CALC_STATUS GROUP BY road_id) AS c2 WHERE c1.st_case=c2.st_case
你可以试试这个:
DELETE t1 FROM table AS t1
LEFT JOIN table t2 ON t1.st_case = t2.st_case
WHERE t1.dist_min > t2.dist_min
下面是我的示例数据。第 3 行和第 4 行具有相同的 st_case(主键),但它们的 dist_min 不同。我想保留具有最小 dist_min 值的行。请注意,可能有 2 个以上的重复行与相同的 st_case 相关联。非常感谢您的帮助!
在 MySQL 中,您可以使用 delete
和 join
:
delete s
from sample s left join
(select st_case, min(dist_min) as mindm
from sample s
group by st_case
) ss
on ss.st_case = s.st_case and s.dist_min > ss.mindm;
我没有测试这个所以请原谅任何语法错误。 SQL ranking functions 可以解决你的问题。本质上,您按一列分组,然后按另一列排名。那你就可以select只有排名第一的
SELECT *
FROM(
SELECT *, Rank() OVER (PARTITION BY 'st_case' Order by Dist_min DESC) as Rank
From 'tbl_Name')
WHERE Rank = '1'
DELETE FROM sample
WHERE dist_min !=(SELECT dist_min FROM (SELECT * FROM sample) sample2
WHERE sample2.st_case = sample.st_case
ORDER BY dist_min
LIMIT 1)
正如 SAM M 所建议的,我不确定您如何拥有具有相同主键的重复行。 但是,如果 st_case 不是您唯一的键,而 table 有一个复合键 或者如果它是一个非关键列, 你可以写一个触发器来控制插入 类似于:
CREATE table CALC_STATUS(id varchar(40), correlatoinToken integer, requirement double)
CREATE TRIGGER keep_min BEFORE INSERT ON CALC_STATUS
FOR EACH row
BEGIN
IF NEW.correlatoinToken = correlatoinToken AND NEW.requirement <= requirement then
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = "A row with similar correlation token with lower requirement already exists";
ELSEIF NEW.correlatoinToken = correlatoinToken AND NEW.requirement > requirement
NEW.requirement = requirement;
END IF;
END;
如果你想查询:
SELECT c1.* FROM CALC_STATUS c1,(SELECT st_case,MIN(dist_min) FROM CALC_STATUS GROUP BY road_id) AS c2 WHERE c1.st_case=c2.st_case
你可以试试这个:
DELETE t1 FROM table AS t1
LEFT JOIN table t2 ON t1.st_case = t2.st_case
WHERE t1.dist_min > t2.dist_min