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 中,您可以使用 deletejoin:

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