2009-05-04 9 views
3

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

ポイントの例の開始:

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

を私は紹介コードを照会する必要がありますが、集約関数の外でそれをやって、私は同様にその場でグループに持っていることを意味し、それは私が欲しいものではありません - Iこの例では顧客あたり1行しか必要ありません。私は本当に最初の注文から紹介コードを気にしています。後で紹介コードを捨てても大丈夫です。

これはPostgreSQLで書かれていますが、他のDBの構文も同様に動作する可能性があります。

拒否されたソリューション:順序が重要であるため、

  • MAX()または分()を使用することはできません。
  • サブクエリは最初は機能しますが、縮尺は変更されません。これは非常に少ない例です。私の実際のクエリには、referral_codeのような数多くのフィールドがあり、最初のインスタンスだけが必要です。サブクエリに複写された場合、メンテナンスの悪夢になるWHERE句が数十件あります。

答えて

0

window functionsが必要です。 これはGROUP BYの種類ですが、引き続き個々の行にアクセスできます。 ただし、Oracle同等物しか使用していません。おそらく、

+0

... 8.4の新機能のようになります。また、これはトリックを行う可能性があります

?残念ながら、リリースされたばかりの新しいバージョンに移行するにはしばらく時間がかかりますが、今はまだ8.2に固執しています(うまくいきません...):\ – David

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 
+2

"GROUP BY customer_id"サブクエリの終わりまで次に、あなたのクエリーが最後のreferral_codeを与えます。結合基準のより大きい値より大きい値をChagneに設定すると、最初のreferral_codeが取得されます。 – ahains

+0

ありがとう、私は私のカットアンドペースト –

0

DATE_CREATEDがCUSTOMER_IDごとに一意であることが保証されている場合は、あなたがこれを行うことができます:

[単純なテーブル]

create table ordertable (customer_id int, order_total int, referral_code char, date_created datetime) 
insert ordertable values (1,10, 'a', '2009-01-01') 
insert ordertable values (2,15, 'b', '2009-01-02') 
insert ordertable values (1,35, 'c', '2009-01-03') 

を[私を置き換えますラメットテーブルの名前は何かより良い:)]

SELECT 
    orderAgg.customer_id, 
    orderAgg.order_sum, 
    referral.referral_code as first_referral_code 
FROM (
     SELECT 
      customer_id, 
      sum(order_total) as order_sum 
     FROM ordertable 
     GROUP BY customer_id 
    ) as orderAgg join (
     SELECT 
      customer_id, 
      min(date_created) as first_date 
     FROM ordertable 
     GROUP BY customer_id 
    ) as dateAgg on orderAgg.customer_id = dateAgg.customer_id 
    join ordertable as referral 
     on dateAgg.customer_id = referral.customer_id 
      and dateAgg.first_date = referral.date_created 
1

さて、実際はかなりシンプルです。 、あなたを今すぐ

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

:のは、第一referral_codeを返すクエリを書いてみましょうし、与えられたCUSTOMER_IDためDATE_CREATED、今

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

まずは、集計を行いますクエリを書いてみましょう

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 

私はそれをテストしませんでしたそれに打ち間違いはありませんが、一般的にうまくいくはずです。

+0

+1にGROUP BYを残したように見えますが、これは2つの場所で更新されるWHERE句を追加する必要があります。 –

+0

これは、この要件がなくても実行できますが、カスタム集計(最初)が必要です。それは難しいことではありません。 –

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 
+0

現在、クエリにはreferral_codeという名前の2つのフィールド(サブクエリである)があり、どちらもGROUP BYにはリストされていません。 –

+0

最初のreferral_codeは実際にはエラーでした。 GROUP BYでそれが欠けているのは、SQLのある方言がそれを必要としないためです。それを指摘してくれてありがとう、ありがとう。 –

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 
関連する問題