1

私は 4 つのテーブルを持っています: ドメイン: :has many => channels:has_many => sales:has_many => visits

このクエリで、すべてのドメイン、チャネル数、販売数、および各ドメインの訪問数を取得しようとしています。

SELECT
    kd.id, kd.domain,
    COUNT(distinct kc.id) AS channels_count,
    COUNT(distinct kv.id) AS visits_count,
    COUNT(distinct kv.ip_address) AS visitors_count,
    COUNT(distinct ks.id) AS sales_count
FROM
    domains AS kd
LEFT JOIN
    channels AS kc
    ON(kc.domain_id=kd.id)
LEFT JOIN
    sales AS ks
    ON(ks.channel_id=kc.id)
LEFT JOIN
    visits AS kv
    ON(kv.channel_id=kc.id)
GROUP BY kd.id

売上高と訪問数のテーブルに数千のレコードがありますが、大きなものはありませんが、クエリには永遠に時間がかかります。それは決して戻ってこない。理由はありますか?

デシベル:postgresql

4

1 に答える 1

2

COUNT(DISTINCT) はリソースを大量に消費する可能性があります。さらに、テーブルの「kd.id」列に多くの重複があり、無数の行が生成される可能性があります。

より効率的な方法は、最初に集計を行い、次に結果を結合することです。次のクエリはあなたが望むことをすると思います(id列は各テーブルで一意であると想定しています):

SELECT kd.id, kd.domain, channels_count, visits_count,
       visitors_count, sales_count
FROM domains kd LEFT JOIN
     (select kc.domain_id, count(*) as channels_count
      from channels kc
      group by kc.domain_id
     ) kc
     ON(kc.domain_id=kd.id) LEFT JOIN
     (select ks.channel_id, count(*) as sales_count
      from sales ks
      group by ks.channel_id
     ) ks
     ON(ks.channel_id=kc.id) LEFT JOIN
     (select kv.channel_id, count(*) as visits_count,
             count(distinct ipaddress) as visitors_count
      from visits kv
      on kv.channel_id
     )
     ON(kv.channel_id=kc.id)

GROUP BY kd.id

于 2012-07-27T01:07:49.937 に答える