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

Postgresを使用した再帰/階層クエリ

    [この回答はゴードンの回答に基づいています]

    arr_timeとdep_timeをTIMEに変更しました 計算を容易にするデータ型。total_timeとwaiting_timeの結果列も追加されました。 :グラフにループが存在する可能性がある場合は、それらを回避する必要があります(おそらく、パスを格納するために配列を使用します)

    WITH RECURSIVE segs AS (
      SELECT f0.flight_num::text as flight
                , src_city, dest_city
                , dep_time AS departure
                , arr_time AS arrival
                , airfare, mileage
                , 1 as hops
                , (arr_time - dep_time)::interval AS total_time
                , '00:00'::interval as waiting_time
      FROM flight f0
      WHERE src_city = 'SLC' -- <SRC_CITY>
      UNION ALL
      SELECT s.flight || '-->' || f1.flight_num::text as flight
                , s.src_city, f1.dest_city
                , s.departure AS departure
                , f1.arr_time AS arrival
                , s.airfare + f1.airfare as airfare
                , s.mileage + f1.mileage as mileage
                , s.hops + 1 AS hops
                , s.total_time + (f1.arr_time - f1.dep_time)::interval AS total_time
                , s.waiting_time + (f1.dep_time - s.arrival)::interval AS waiting_time
      FROM segs s
         JOIN flight f1
           ON f1.src_city = s.dest_city
           AND f1.dep_time > s.arrival -- you can't leave until you are there
    )
    SELECT *
    FROM segs
    WHERE dest_city = 'LA' -- <DEST_CITY>
    ORDER BY airfare desc
        ;
    

    参考:テーブル構造の変更:

    create table flight
      ( flight_num BIGSERIAL PRIMARY KEY
      , src_city varchar
      , dest_city varchar
      , dep_time TIME
      , arr_time TIME
      , airfare INTEGER
      , mileage INTEGER
    );
    

    そしてデータへ:

    insert into flight VALUES
      (101,    'Montreal',          'NY',                   '05:30',     '06:45',    180,      170),
      (102,    'Montreal',          'Washington',           '01:00',     '02:35',    100,      180),
      (103,    'NY',                'Chicago',              '08:00',     '10:00',    150,      300),
      (105,    'Washington',        'KansasCity',           '06:00',     '08:45',    200,      600),
      (106,    'Washington',        'NY',                   '12:00',     '13:30',     50,       80),
      (107,    'Chicago',           'SLC',                  '11:00',     '14:30',    220,      750),
      (110,    'KansasCity',        'Denver',               '14:00',     '15:25',    180,      300),
      (111,    'KansasCity',        'SLC',                  '13:00',     '15:30',    200,      500),
      (112,    'SLC',               'SanFran',              '18:00',     '19:30',     85,      210),
      (113,    'SLC',               'LA',                   '17:30',     '19:00',    185,      230),
      (115,    'Denver',            'SLC',                  '15:00',     '16:00',     75,      300),
      (116,    'SanFran',           'LA',                   '22:00',     '22:30',     50,       75),
      (118,    'LA',                'Seattle',              '20:00',     '21:00',    150,      450);
    


    1. SQLServerシステムデータベースのメンテナンス

    2. 2つのテーブル間で2つの列の値を交換します

    3. C ++コネクタでsetBlob()を使用してバイナリデータを設定する方法

    4. 循環結合、再帰検索の防止