UPDATE中的内部SELECT不更新所有行Oracle

时间:2014-10-27 19:49:57

标签: sql oracle

我在Oracle 11 G上运行它 我试图使用TABLE2.CLASSNAME中的值更新TABLE1中的列CLASS。 用于JOIN的键是TABLE1.T1ID = TABLE2.T2ID TABLE2可以具有相同ID的多个CLASSNAME值。

可用于更新的列是:

表1:

TID - Identifier
LOADDT - Date all records were loaded

表2:

T2ID - Identifier
LOADDT - Date all records were loaded
ENROLLDATE - A date updated when the student enrolled in the class. The latest date will have the most recent class he enrolled in.

这是我的UPDATE语句:

UPDATE table1 fs
SET    class =
          (SELECT a.classname
           FROM   table2 a
           WHERE      TRIM (a.t2id) = TRIM (fs.t1id)
                  AND TO_DATE (a.loaddt, 'DD-MON-YY') =
                         TO_DATE ( (SELECT MAX (loaddt)
                                    FROM   table2 aa
                                    WHERE  TRIM (a.t2id) = TRIM (aa.t2id)),
                                  'DD-MON-YY' AND ROWNUM = 1)
                  AND ROWNUM = 1)
WHERE  TO_DATE (loaddt, 'DD-MON-YY') =
          TO_DATE ( (SELECT MAX (loaddt) FROM table1), 'DD-MON-YY');

即使TABLE2.CLASSNAME没有NULL,我的更新似乎也会留下很多行NULL(90%)。

我的更新中没有使用ENROLLDATE。

我错过了什么吗?你能帮忙吗?

2 个答案:

答案 0 :(得分:1)

UPDATE TABLE1 fs
SET  CLASS=
    (
        select a.CLASSNAME from (
            select T2ID, LOADDT, CLASSNAME, 
                   row_number() over(partition by T2ID order by LOADDT desc) rw  
            from TABLE2) a 
        where a.rw = 1 and TRIM(a.T2ID) = TRIM(fs.T1ID)
    )
-- do you really need this condition? 
WHERE TO_DATE(LOADDT,'DD-MON-YY')=TO_DATE((SELECT MAX(LOADDT) FROM TABLE1),'DD-MON-YY');

答案 1 :(得分:1)

ROWNUM = 1几乎总是可以翻译为“选择准随机行”。在许多情况下(比如你的),你使用分析查询要好得多,如果没有其他原因,那么它们不容易出错。

这个答案基于@ Multisync的解决方案,但我不喜欢在SET子句中使用子查询。更新相关行时,我更喜欢MERGE

MERGE INTO table1 fs
USING      (SELECT classname, t2id
            FROM   (SELECT t2id,
                           classname,
                           ROW_NUMBER ()
                              OVER (PARTITION BY t2id ORDER BY loaddt DESC)
                              rw
                    FROM   table2) a
            WHERE  a.rw = 1) b
ON         (TRIM (b.t2id) = TRIM (fs.t1id))
WHEN MATCHED THEN
   UPDATE SET
      class = b.classname
      WHERE      TO_DATE (loaddt, 'DD-MON-YY') =
                    TO_DATE ( (SELECT MAX (loaddt) FROM table1), 'DD-MON-YY');