PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Bagaimana cara sederhana dan efisien meminta hubungan bersarang di SQL?

Seperti halnya kueri apa pun, metode yang paling efisien adalah "itu tergantung". Ada banyak variabel yang dimainkan - jumlah baris dalam tabel, panjang baris, apakah ada indeks, RAM di server, dll.

Cara terbaik yang dapat saya pikirkan untuk menangani masalah semacam ini (berpikir tentang pemeliharaan dan pendekatan efisiensi yang baik) adalah dengan menggunakan CTE, yang memungkinkan Anda membuat hasil sementara dan menggunakan kembali hasil itu di seluruh kueri Anda. CTE menggunakan kata kunci WITH, dan pada dasarnya alias hasil sebagai tabel, sehingga Anda dapat BERGABUNG melawannya beberapa kali:

WITH user_memberships AS (
    SELECT *
    FROM memberships
    WHERE user_id = ${id}
), user_apps AS (
    SELECT *
    FROM apps
    INNER JOIN user_memberships
        ON user_memberships.team_id = apps.team_id
), user_collections AS (
    SELECT *
    FROM collections
    INNER JOIN user_memberships
        ON user_memberships.team_id = collections.team_id
), user_webhooks AS (
    SELECT *
    FROM webhooks
    LEFT OUTER JOIN user_collections ON user_collections.id = webhooks.collection_id
    INNER JOIN user_memberships
        ON user_memberships.team_id = webhooks.team_id
        OR user_memberships.team_id = user_collections.team_id
)

SELECT events.* 
FROM events
WHERE app_id IN (SELECT id FROM user_apps)
OR collection_id IN (SELECT id FROM user_collections)
OR membership_id IN (SELECT id FROM user_memberships)
OR team_id IN (SELECT team_id FROM user_memberships)
OR user_id = ${id}
OR webhook_id IN (SELECT id FROM user_webhooks)
;

Manfaat melakukannya dengan cara ini adalah:

  1. Setiap CTE dapat memanfaatkan indeks pada predikat GABUNG yang sesuai dan mengembalikan hasil hanya untuk subset itu lebih cepat, daripada meminta perencana eksekusi untuk menyelesaikan serangkaian predikat kompleks
  2. CTE dapat dipertahankan satu per satu, membuat pemecahan masalah dengan subset menjadi lebih mudah
  3. Anda tidak melanggar prinsip KERING
  4. Jika CTE memiliki nilai di luar kueri, Anda dapat memindahkannya ke prosedur tersimpan dan merujuknya sebagai gantinya


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara menangani nilai opsional yang dikembalikan oleh kueri menggunakan peti postgres?

  2. Mengembalikan nilai individu nol dengan postgres tablefunc crosstab()

  3. Menggunakan pg_notify dalam fungsi pemicu PostgreSQL

  4. GALAT:kolom relasi tidak ada PostgreSQL, Tidak dapat menjalankan kueri penyisipan

  5. Setara dengan strftime di Postgres