代码之家  ›  专栏  ›  技术社区  ›  SwapnaSubham Das

如何从表中检索最新数据

  •  0
  • SwapnaSubham Das  · 技术社区  · 5 年前

    目前,我正在从事一个项目,我需要从一个表中提取最新的数据用于报表目的。下面是示例表structure:-

    enter image description here 每个学生都有几门课程,编程语言的课程号是+ve,非编程语言的课程号是-ve。我想为每个学生提取最新的编程语言和非编程语言课程id。

    我使用下面的SQL查询并能够提取数据。

    CREATE TABLE COURSE
        ("STUDENT_ID" int, "COURSE_ID" int, "COURSE_NAME" varchar2(31), "COURSE_START_DATE" timestamp)
    ;
    
    INSERT ALL 
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100001, -100, 'C Programming Language', '04-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100001, -200, 'Java Programming Language', '11-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100001, -300, 'C# Programming Language', '07-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100001, 100, 'Data Structure and algorithms', '05-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100001, 200, 'Computer Graphics', '13-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100001, 300, 'Networking', '02-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100002, -300, 'C# Programming Language', '12-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100002, -400, 'Python Programming Language', '07-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100002, -500, 'JavaScript Programming Language', '08-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100002, 100, 'Data Structure and algorithms', '17-Jan-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100002, 300, 'Computer Graphics', '26-Jan-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100002, 400, 'DataBase Management', '10-Jan-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100003, -500, 'JavaScript Programming Language', '07-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100003, -600, 'SQL', '13-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100003, -200, 'Java Programming Language', '17-Jan-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100003, 300, 'Networking', '04-Feb-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100003, 400, 'DataBase Management', '05-Jan-2019 12:00:00 AM')
        INTO COURSE ("STUDENT_ID", "COURSE_ID", "COURSE_NAME", "COURSE_START_DATE")
             VALUES (100003, 600, 'Cryptography', '18-Jan-2019 12:00:00 AM')
    SELECT * FROM dual
    ;
    
    SELECT STUDENT_ID
    ,COURSE_ID
    ,COURSE_NAME
    ,COURSE_START_DATE
      FROM (
    SELECT 
    ROW_NUMBER() OVER(PARTITION BY STUDENT_ID ORDER BY COURSE_START_DATE DESC) AS ROW_NUM
    ,STUDENT_ID
    ,COURSE_ID
    ,COURSE_NAME
    ,COURSE_START_DATE
      FROM
    COURSE
    WHERE COURSE_ID  0) TEMP1 WHERE TEMP1.ROW_NUM = 1;
    

    enter image description here

    但问题是真正的表非常大。大约有85k行,这个查询需要一些时间。有没有其他更好的办法。我正在使用Oracle 11g R2。请建议

    这是SQLfiddle链接 http://sqlfiddle.com/#!4/b3fe1/8

    2 回复  |  直到 5 年前
        1
  •  3
  •   Fahmi    5 年前

    你可以在下面尝试-你需要添加 PARTITION BY STUDENT_ID,case when course_id<0 then 1 else 2 end order by COURSE_START_DATE DESC 在过度的混乱中

    SELECT STUDENT_ID,COURSE_ID,COURSE_NAME,COURSE_START_DATE
    FROM 
    (
      SELECT 
      ROW_NUMBER() OVER(PARTITION BY STUDENT_ID,case when course_id<0 then 1 else 2 end order by COURSE_START_DATE DESC) AS ROW_NUM
    , STUDENT_ID,COURSE_ID,COURSE_NAME,COURSE_START_DATE FROM COURSE
     )TEMP1 WHERE TEMP1.ROW_NUM = 1;
    
        2
  •  0
  •   JohnHC    5 年前

    将CTE与行号一起使用,然后合并它们

    with pro as 
    (
    select t1.*, row_number() over(partition by student_id order by course_start_date desc) rn
    from course 
    where course_id > 0 -- programming
    )
    , nonpro as 
    (
    select t1.*, row_number() over(partition by student_id order by course_start_date desc) rn
    from course 
    where course_id < 0 -- non-programming
    )
    select *
    from pro
    where rn = 1
    union
    select *
    from nonpro
    where rn = 1
    
        3
  •  0
  •   MT0    5 年前

    您可以使用查询和添加 SIGN( course_id ) 到分区:

    查询 :

    SELECT STUDENT_ID
         , COURSE_ID
         , COURSE_NAME
         , COURSE_START_DATE
    FROM (
      SELECT ROW_NUMBER() OVER (
               PARTITION BY STUDENT_ID, SIGN( COURSE_ID )
               ORDER BY COURSE_START_DATE DESC
             ) AS ROW_NUM
           , STUDENT_ID
           , COURSE_ID
           , COURSE_NAME
           , COURSE_START_DATE
      FROM   COURSE
      WHERE COURSE_ID != 0
    )
    WHERE  ROW_NUM = 1;
    

    输出 :

    STUDENT_ID | COURSE_ID | COURSE_NAME               | COURSE_START_DATE           
    ---------: | --------: | :------------------------ | :---------------------------
        100001 |      -200 | Java Programming Language | 11-FEB-19 12.00.00.000000 AM
        100001 |       200 | Computer Graphics         | 13-FEB-19 12.00.00.000000 AM
        100002 |      -300 | C# Programming Language   | 12-FEB-19 12.00.00.000000 AM
        100002 |       300 | Computer Graphics         | 26-JAN-19 12.00.00.000000 AM
        100003 |      -600 | SQL                       | 13-FEB-19 12.00.00.000000 AM
        100003 |       300 | Networking                | 04-FEB-19 12.00.00.000000 AM
    

    数据库<&燃气轮机;小提琴 here

        4
  •  0
  •   LukStorms    5 年前

    NOT EXISTS

    因为如果你想要最新课程开始日期的记录 对一个学生来说。

    (除非有2个具有相同的最大日期,否则它将同时返回这两个)

    SELECT 
     STUDENT_ID, 
     COURSE_ID, 
     COURSE_NAME, 
     COURSE_START_DATE
    FROM COURSE t
    WHERE COURSE_ID != 0
    AND NOT EXISTS
    (
      SELECT 1
      FROM COURSE d
      WHERE d.STUDENT_ID = t.STUDENT_ID
        AND d.COURSE_START_DATE > t.COURSE_START_DATE
        AND SIGN(d.COURSE_ID) = SIGN(t.COURSE_ID)
        AND d.COURSE_ID != 0
    )
    ORDER BY SIGN(COURSE_ID), STUDENT_ID
    

    这样的查询可能会受益于学生ID上的非唯一索引。

    测试 数据库<&燃气轮机;小提琴 here

    SELECT 
     STUDENT_ID, 
     COURSE_ID, 
     COURSE_NAME, 
     COURSE_START_DATE
    FROM COURSE t
    WHERE COURSE_ID != 0
    ORDER BY row_number() over(partition by student_id, SIGN(COURSE_ID) order by course_start_date desc)
    FETCH FIRST ROW WITH TIES