【问题标题】:How to delete the rows with three same data columns and one different data column如何删除具有三个相同数据列和一个不同数据列的行
【发布时间】:2019-11-18 18:49:57
【问题描述】:

我有一张桌子"MARK_TABLE",如下所示。

如何删除具有相同"STUDENT""COURSE""SCORE" 值的行?

| ID | STUDENT | COURSE | SCORE |
|----|---------|--------|-------|
| 1  |    1    |    1   |  60   |
| 3  |    1    |    2   |  81   |
| 4  |    1    |    3   |  81   |
| 9  |    2    |    1   |  80   |
| 10 |    1    |    1   |  60   |
| 11 |    2    |    1   |  80   |

现在我已经过滤了我想要保留的数据,但没有 "ID"...

SELECT student, course, score FROM mark_table
INTERSECT
SELECT student, course, score FROM mark_table

输出:

| STUDENT | COURSE | SCORE |
|---------|--------|-------|
|    1    |    1   |  60   |
|    1    |    2   |  81   |
|    1    |    3   |  81   |
|    2    |    1   |  80   |

【问题讨论】:

  • 一种简单的方法是选择要保留到临时表中的数据,清除源表,然后将临时表数据重新插入到源表中。
  • 但是我不知道如何选择带有"ID"的数据。一旦我选择了"ID',结果就不同了。这不是我想要的。
  • SELECT STUDENT, COURSE, SCORE, MAX(ID) FROM MARK_TABLE GROUP BY STUDENT, COURSE, SCORE 这样做怎么样?
  • 这次成功了。现在我需要弄清楚如何删除不在此输出中的行...
  • Tejash's Answer 做到了这一点。

标签: sql oracle duplicates sql-delete


【解决方案1】:

使用以下查询删除所需的行:

DELETE FROM MARK_TABLE M
WHERE
    EXISTS (
        SELECT
            1
        FROM
            MARK_TABLE M_IN
        WHERE
            M.STUDENT = M_IN.STUDENT
            AND M.COURSE = M_IN.COURSE
            AND M.SCORE = M_IN.SCORE
            AND M.ID < M_IN.ID
    )

输出

db<>fiddle demo

干杯!!

【讨论】:

  • 巧妙的技巧,使用 id 排序来决定保留哪个。
  • 为什么是"SELECT 1""1" 是什么意思?
  • @Nicole the 1 在他的示例中无关紧要,它是“字面上任何记录”的代表。查询的运行方式是“如果一个学生、分数、课程组合存在多个记录,请删除所有记录中不具有最高 ID 的任何记录”
  • 那么我可以用一个随机数来代表“字面上的任何记录”吗?或者我只能使用"1"
  • 您甚至可以使用NULL 代替"1"Select clause 与查询无关
【解决方案2】:

使用distinct

SELECT distinct student, course, score FROM mark_table

【讨论】:

    【解决方案3】:

    假设您不只是想选择要保留的唯一数据(您提到您已经这样做了),您可以按照以下步骤进行:

    1. 创建一个临时表来保存您要保留的数据
    2. 将要保留的数据插入到临时表中
    3. 清空源表
    4. 将要保留的数据重新插入到源表中。

    【讨论】:

      【解决方案4】:
      select * from
      (
      select row_number() over (partition by student,course,score order by score) 
      rn,student,course,score from mark_table
      ) t
      where rn=1
      

      【讨论】:

      • 这对于有学生两次以不同分数参加同一课程的记录会失败,而 OP 指出他们只想过滤所有 3 个匹配的记录。
      【解决方案5】:

      将 CTE 与 RowNumber 一起使用

      create table #MARK_TABLE (ID int, STUDENT  int, COURSE  int, SCORE  int)
      insert into #MARK_TABLE 
      values 
      (1,1,1,60),
      (3,1,2,81),
      (4,1,3,81),
      (9,2,1,80),
      (10,1,1,60),
      (11,2,1,80)
      
      ;with cteDeleteID as(
      Select id, row_number() over (partition by student,course,score order by score) [row_number]  from #MARK_TABLE
      )
      delete from #MARK_TABLE where id in
      (
       select id from cteDeleteID where [row_number] != 1
      )
      
      select * from #MARK_TABLE
      drop table #MARK_TABLE    
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-04
        • 1970-01-01
        • 2020-11-17
        • 2016-08-31
        • 2014-12-15
        • 1970-01-01
        • 1970-01-01
        • 2021-09-29
        相关资源
        最近更新 更多