【问题标题】:Oracle SQL - update 2 columns in row with the oldest dateOracle SQL - 用最旧的日期更新行中的 2 列
【发布时间】:2018-10-01 03:29:29
【问题描述】:

我正在尝试连续更新 2 列。应该更新的行是最旧的行duedate

table chorecompletion 描述为:

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 CHOREID                                   NOT NULL NUMBER(38)
 GROUPID                                   NOT NULL NUMBER(38)
 DUEDATE                                   NOT NULL DATE
 COMPLETEDDATE                                      DATE
 COMPLETEDBY                                        NUMBER(38)

此查询返回我要更新的行

select *
from 
(
        select choreid, duedate, row_number() 
        over (partition by choreid order by duedate) as rn 
        from chorecompletion where choreid = 12 and groupid = 6
)
where rn = 1;

我需要帮助的地方是如何在我的更新语句中使用这个查询,特别是我的 where 子句

我目前的尝试:

update chorecompletion 
set completeddate = sysdate, completedby=1
where --How to get the result of the previous query here?

对我的逻辑的任何帮助将不胜感激。

期望结果示例:

更新前:

CHOREID      GROUPID    DUEDATE     COMPLETEDDATE      COMPLETEDBY
-------------------------------------------------------------------
  12          6        2018-11-1
  12          6        2018-10-1

更新后

CHOREID      GROUPID    DUEDATE     COMPLETEDDATE      COMPLETEDBY
-------------------------------------------------------------------
  12          6        2018-11-1 
  12          6        2018-10-1      2018-09-30            1

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    这样的?

    SQL> create table test
      2  (choreid number,
      3   groupid number,
      4   duedate date,
      5   completeddate date,
      6   completedby number
      7  );
    
    Table created.
    
    SQL> insert into test
      2    select 12, 6, date '2018-01-11', null, null from dual union all
      3    select 12, 6, date '2018-01-10', null, null from dual;
    
    2 rows created.
    
    SQL> update test t set
      2    t.completeddate = sysdate,
      3    t.completedby = 1
      4  where t.duedate = (select min(t1.duedate)
      5                     from test t1
      6                     where t1.choreid = t.choreid
      7                       and t1.groupid = t.groupid)
      8    and t.choreid = 12
      9    and t.groupid = 6;
    
    1 row updated.
    
    SQL> select * From test;
    
       CHOREID    GROUPID DUEDATE    COMPLETEDD COMPLETEDBY
    ---------- ---------- ---------- ---------- -----------
            12          6 2018-01-11
            12          6 2018-01-10 2018-09-30           1
    
    SQL>
    

    【讨论】:

    • 这最终成为我实施的最简单的解决方案。起初它不起作用,但我意识到这是因为在我的示例数据集中,我已经拥有相同的 choreid 和 groupid 以及 completeddatecompletedby,所以您的解决方案只是更新已经完成的结果。在嵌套的内部查询中添加行 and completeddate is null 为我解决了这个问题。感谢您的帮助!
    【解决方案2】:

    您可以使用MERGE 语句并可以加入ROWID 伪列,以便您可以直接关联到匹配的行: SQL Fiddle

    Oracle 11g R2 架构设置

    CREATE TABLE chorecompletion ( choreid, groupid, duedate, completeddate, completedby ) AS
      SELECT 12, 6, DATE '2018-09-29', CAST( null AS DATE ), CAST( null AS NUMBER ) FROM DUAL UNION ALL
      SELECT 12, 6, DATE '2018-09-30', null, null FROM DUAL;
    

    查询 1

    MERGE INTO chorecompletion dst
    USING (
      SELECT ROWID AS rid
      FROM   (
        SELECT *
        FROM   chorecompletion
        WHERE  choreid = 12
        AND    groupid = 6
        ORDER BY duedate ASC
      )
      WHERE ROWNUM = 1
    ) src
    ON ( src.RID = dst.ROWID )
    WHEN MATCHED THEN
      UPDATE
      SET completeddate = sysdate,
          completedby   = 1
    

    Results

    1 Row Updated.
    

    查询 2

    SELECT * FROM chorecompletion
    

    Results

    | CHOREID | GROUPID |              DUEDATE |        COMPLETEDDATE | COMPLETEDBY |
    |---------|---------|----------------------|----------------------|-------------|
    |      12 |       6 | 2018-09-29T00:00:00Z | 2018-09-30T18:42:45Z |           1 |
    |      12 |       6 | 2018-09-30T00:00:00Z |               (null) |      (null) |
    

    查询 3:您还可以使用带有 ROWID 伪列的 UPDATE 语句:

    UPDATE chorecompletion dst
    SET    completeddate = sysdate,
           completedby   = 2
    WHERE  ROWID = (
      SELECT ROWID
      FROM   (
        SELECT ROW_NUMBER() OVER ( PARTITION BY choreid ORDER BY duedate ) rn
        FROM   chorecompletion
        WHERE  choreid = 12
        AND    groupid = 6
        ORDER BY duedate ASC
      )
      WHERE rn = 1
    )
    

    Results

    1 Row Updated.
    

    查询 4

    SELECT * FROM chorecompletion
    

    Results

    | CHOREID | GROUPID |              DUEDATE |        COMPLETEDDATE | COMPLETEDBY |
    |---------|---------|----------------------|----------------------|-------------|
    |      12 |       6 | 2018-09-29T00:00:00Z | 2018-09-30T18:42:45Z |           2 |
    |      12 |       6 | 2018-09-30T00:00:00Z |               (null) |      (null) |
    

    【讨论】:

      【解决方案3】:

      您可以使用相关子查询。如果我理解正确:

      update chorecompletion
          set completeddate = (select min(duedate)
                               from chorecompletion cc
                               where cc.choreid = chorecompletion.coreid
                              )
          where choreid = 12 and groupid = 6 
      

      【讨论】:

      • =set 之后,是我不知道的语法还是错误?
      • 这会将完成日期设置为具有相同 choreid 的最早截止日期(这不是 OP 想要的),但它也不会将最早截止日期与 @987654325 相关联@ of 6 所以你可能会得到一个不符合数据的duedate
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-09
      • 1970-01-01
      • 2021-04-30
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      相关资源
      最近更新 更多