2017-08-31 37 views
0

我有一个这样的表,其中,假设为了举例,NAME是唯一标识符。仅使用SQL中的MAX函数更新重复行

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

一些NAME■找一个以上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” 和 “65岁以下”=> MAX = “65岁以下” - 最低
  • “66-74”和“超过75”=> MAX =“超过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 
+1

您更新查询将需要逻辑选择重复的情况下,更小的年龄,但考虑到它的存储为文本,有时在里面的话,这可能会导致挑战性的查询 –

+0

**唯一标识符**的绝佳示例! – mathguy

回答

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) 
+0

就像一个魅力工作! – Mihael