sql >> データベース >  >> RDS >> Oracle

LEFTOUTERJOINの最初の行を取得する

    KEEP DENSE_RANKをお試しください

    データソース:

    CREATE TABLE person
        (person_id int primary key, firstname varchar2(4), lastname varchar2(9))
    /
    INSERT ALL
        INTO person (person_id, firstname, lastname)
             VALUES (1, 'john', 'lennon')
        INTO person (person_id, firstname, lastname)
             VALUES (2, 'paul', 'mccartney')
    SELECT * FROM dual;
    
    
    
    CREATE TABLE address
        (person_id int, address_id int primary key, city varchar2(8))
    /
    INSERT ALL
        INTO address (person_id, address_id, city)
             VALUES (1, 1, 'new york')
        INTO address (person_id, address_id, city)
             VALUES (1, 2, 'england')
        INTO address (person_id, address_id, city)
             VALUES (1, 3, 'japan')
        INTO address (person_id, address_id, city)
             VALUES (2, 4, 'london')
    SELECT * FROM dual;
    

    クエリ:

        select  
    
          p.person_id, p.firstname, p.lastname,
    
          x.recent_city
    
        from person p
        left join (
    
            select person_id,      
    
                min(city) -- can change this to max(city). will work regardless of min/max
    
                -- important you do this to get the recent: keep(dense_rank last)
    
                keep(dense_rank last order by address_id) 
                   as recent_city
    
            from address 
            group by person_id
    
    
        ) x on x.person_id = p.person_id
    

    ライブテスト: http://www.sqlfiddle.com/#!4/7b1c9/ 2

    すべてのデータベースがOracleのKEEPDENSE_RANKウィンドウ関数と同様の機能を備えているわけではありません。代わりにプレーンウィンドウ関数を使用できます。

    select  
    
      p.person_id, p.firstname, p.lastname,
    
      x.recent_city, x.pick_one_only
    
    from person p
    left join (
    
        select 
    
            person_id,      
    
            row_number() over(partition by person_id order by address_id desc) as pick_one_only,
            city as recent_city
    
        from address 
    
    
    
    ) x on x.person_id = p.person_id and x.pick_one_only = 1
    

    ライブテスト: http://www.sqlfiddle.com/#!4/7b1c9/ 48

    または、タプルテストを使用します。ウィンドウ関数をサポートしていないデータベースで機能します:

    select  
    
      p.person_id, p.firstname, p.lastname,
    
      x.recent_city
    
    from person p
    left join (
    
        select   
            person_id,city as recent_city    
        from address 
        where (person_id,address_id) in
    
              (select person_id, max(address_id)
               from address
               group by person_id)
    
    
    
    ) x on x.person_id = p.person_id 
    

    ライブテスト: http://www.sqlfiddle.com/#!4/7b1c9/ 21

    ただし、前のコードのように、すべてのデータベースがタプルテストをサポートしているわけではありません。代わりにJOINを使用できます:

    select  
    
      p.person_id, p.firstname, p.lastname,
    
      x.recent_city
    
    from person p
    left join (
    
        select 
    
            address.person_id,address.city as recent_city
    
        from address 
        join 
        (
              select person_id, max(address_id) as recent_id
               from address
               group by person_id
        ) r 
        ON address.person_id = r.person_id
        AND address.address_id = r.recent_id
    
    
    
    ) x on x.person_id = p.person_id 
    

    ライブテスト: http://www.sqlfiddle.com/#!4/7b1c9/ 24



    1. 非同期スレーブを使用したGaleraクラスターのハイブリッドOLTP/分析データベースワークロード

    2. MySQLiを使用したバッファなしクエリ?

    3. MySQL-SELECT * INTO OUTFILE LOCAL?

    4. PythonでMySQLdbを使用してmysqlで挿入した後、どのようにして安全かつ効率的に行IDを取得しますか?