【问题标题】:Update duplicate rows only with a MAX function in SQL仅使用 SQL 中的 MAX 函数更新重复行
【发布时间】:2017-08-31 11:32:55
【问题描述】:

我有一个这样的表,假设为了一个例子,NAME 是一个唯一标识符。

NAME    AGE         VALUE
Jack    Under 65    3
Jack    66-74       5 
John    66-74       7
John    Over 75     9
Gill    25-35       11

一些NAMEs 有多个AGE,这是不可取的,因为这是由于数据不干净。

我的目标是将重复项更新为每个NAME 中只有一个AGE。因此,所需的输出是:

NAME    AGE         VALUE
Jack    Under 65    3
Jack    Under 65    5 
John    66-74       7
John    66-74       9
Gill    25-35       11

类似这样的 UPDATE 语句应该可以工作,但它不能。

UPDATE table t1
SET t1.age=MAX(t1.age)
WHERE EXISTS (SELECT COUNT(t2.AGE)
              FROM table t2
              WHERE t1.NAME=t2.NAME
              GROUP BY t2.NAME
              HAVING COUNT(t2.AGE) > 1)

SQL Error: ORA-00934: group function is not allowed here

第二期

即使我得到了上述声明,还有第二个问题。想法是在字符串上使用MAX(或MIN)函数为组内的所有重复设置相同的值。

但不幸的是,这也无法按预期工作。为了保持一致性,理想情况下,年龄将默认为最低年龄组。但是因为MAX/MIN比较字符串的字母顺序,这会给出,例如:

  • "66-74" 和 "Under 65" => MAX="Under 65" -- 最低
  • "66-74" 和 "Over 75" => MAX="Over 75" -- 最高

只有四个年龄段,可以指定自定义顺序吗?

  • NB1:我正在使用 Oracle SQL。
  • NB2:我不介意是否有办法使用 SELECT 而不是 UPDATE 语句来实现结果。

可重现的示例

SELECT 'Jack' as NAME, 'Under 65' as AGE, 3 as VALUE from dual
UNION ALL
SELECT 'Jack' as NAME, '66-74' as AGE, 5 as VALUE from dual
UNION ALL
SELECT 'John' as NAME, '66-74' as AGE, 7 as VALUE from dual
UNION ALL
SELECT 'John' as NAME, 'Over 75' as AGE, 9 as VALUE from dual
UNION ALL
SELECT 'Gill' as NAME, '25-35' as AGE, 11 as VALUE from dual

【问题讨论】:

  • 您的更新查询将需要逻辑在重复的情况下选择较小的年龄,但鉴于它以文本形式存储,有时其中包含单词,这可能会导致查询具有挑战性。
  • 唯一标识符的好例子!

标签: sql oracle sql-update oracle12c


【解决方案1】:

您可以使用case when 子句定义自定义订单,然后使用解析max()。这适用于给定的示例:

update t1 set age = (
    select max(age) keep (dense_rank last 
           order by case when age = 'Over 75'  then 1
                         when age = '66-74'    then 2
                         when age = 'Under 65' then 3
                         when age = '25-35'    then 4
                    end)
    from t1 tx where tx.name = t1.name )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-06
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多