3

共通の ID でグループ化された複数のレコードに対して集計関数を実行しています。問題は、グループ化されたレコード内で異なる可能性がある他のフィールドもエクスポートしたいのですが、レコードの 1 つ (クエリの ORDER BY に従って最初のフィールド) から特定のフィールドを取得したいことです。

出発点の例:

SELECT
  customer_id,
  sum(order_total),
  referral_code
FROM order
GROUP BY customer_id
ORDER BY date_created

紹介コードを照会する必要がありますが、集計関数の外でそれを行うということは、そのフィールドでもグループ化する必要があることを意味します。これは私が望んでいることではありません。この例では、顧客ごとに正確に 1 つの行が必要です。私は本当に最初の注文からの紹介コードだけを気にします.それ以降の紹介コードは喜んで破棄します.

これは PostgreSQL にありますが、他の DB の構文が十分に類似している可能性があります。

拒否されたソリューション:

  • 順序が重要なため、max() または min() は使用できません。
  • サブクエリは最初は機能するかもしれませんが、スケーリングしません。これは非常に縮小された例です。私の実際のクエリには、最初のインスタンスのみが必要な referral_code のような数十のフィールドと、サブクエリで重複するとメンテナンスの悪夢になる数十の WHERE 句があります。
4

6 に答える 6

1

まあ、それは実際にはかなり単純です。

まず、集計を行うクエリを書きましょう。

select customer_id, sum(order_total)
from order
group by customer_id

それでは、指定された customer_id に対して最初の referral_code と date_created を返すクエリを書きましょう。

select distinct on (customer_id) customer_id, date_created, referral_code
from order
order by customer_id, date_created

これで、2 つの選択を簡単に結合できます。

select
    x1.customer_id,
    x1.sum,
    x2.date_created,
    x2.referral_code
from
    (
        select customer_id, sum(order_total)
        from order
        group by customer_id
    ) as x1
    join
    (
        select distinct on (customer_id) customer_id, date_Created, referral_code
        from order
        order by customer_id, date_created
    ) as x2 using ( customer_id )
order by x2.date_created

私はそれをテストしなかったので、タイプミスがあるかもしれませんが、一般的にはうまくいくはずです。

于 2009-05-04T21:55:46.850 に答える
0

このようなものはうまくいきますか?

SELECT
  customer_id,
  sum(order_total),
  (SELECT referral_code 
   FROM order o 
   WHERE o.customer_id = order.customer_id 
   ORDER BY date_created 
   LIMIT 1) AS customers_referral_code
FROM order
GROUP BY customer_id, customers_referral_code
ORDER BY date_created

これは 2 つの場所で WHERE 句を維持する必要はなく、順序の重要性を維持しますが、referral_code のような「数十のフィールド」が必要な場合はかなり複雑になります。また、かなり遅いです (少なくとも MySQL では)。

referral_code注文ではなく顧客と 1 対 1 で論理的に関連付けられているため、注文テーブルではなく、顧客テーブルにあるはずの数十のフィールドのように思えます。それらをそこに移動すると、クエリがはるかに簡単になります。

これもトリックを行うかもしれません:

SELECT
  o.customer_id,
  sum(o.order_total),
  c.referral_code, c.x, c.y, c.z
FROM order o LEFT JOIN (
    SELECT referral_code, x, y, z
    FROM orders c 
    WHERE c.customer_id = o.customer_id 
    ORDER BY c.date_created
    LIMIT 1
) AS c
GROUP BY o.customer_id, c.referral_code
ORDER BY o.date_created
于 2009-05-04T23:00:00.877 に答える
0

ウィンドウ関数が必要です。これは一種の GROUP BY ですが、個々の行にアクセスすることはできます。ただし、Oracleの同等のもののみを使用しました。

于 2009-05-04T20:21:43.567 に答える
0
SELECT  customer_id, order_sum,
        (first_record).referral, (first_record).other_column
FROM    (
        SELECT  customer_id,
                SUM(order_total) AS order_sum,
                (
                SELECT  oi
                FROM    order oi
                WHERE   oi.customer_id = o.customer_id
                LIMIT 1
                ) AS first_record
        FROM    order o
        GROUP BY
                customer_id
        ) q
于 2009-05-05T15:16:05.273 に答える
0

おそらく次のようなものです:

SELECT
     O1.customer_id,
     O1.referral_code,
     SQ.total
FROM
     Orders O1
LEFT OUTER JOIN Orders O2 ON
     O2.customer_id = O1.customer_id AND
     O2.date_created < O1.date_created
INNER JOIN (
     SELECT
          customer_id,
          SUM(order_total) AS total
     FROM
          Orders
     GROUP BY
          customer_id
     ) SQ ON SQ.customer_id = O1.customer_id
WHERE
     O2.customer_id IS NULL
于 2009-05-04T20:34:40.667 に答える