2017-06-18 3 views
2

私は2つのSQLテーブルを持っています.1つは顧客のアドレス帳で、もう1つは購入ログです。私が見たいと思って何SQL無期限のサブジェクトを日付で結合して注文する

カスタマー表

Cust ID  Cust Name 
1   Adam 
2   Brian 
3   Charles 
4   Dave 
... 

購入履歴

Customer ID   Price   Date 
1     $100   1996-01-20 
1     $200   1995-01-01 
2     $70   1999-05-22 
... 

は、顧客名と直近の購入の価格です。 だから表は次のようになります。

Customer Name  Price  
Adam    $100 
Brian    $70 
... 

私は(限界、によって順序のように、そして参加)を使用するために機能するものの一般的な考えを持っていると思うが、私は一緒にそれをすべて置くのトラブルを抱えています。

問題を悪化させるためには、同じ日に顧客が複数の購入をしている場合に対処する方法を見つけ出す必要があります。デフォルトでは、最初の価格が表示されると思いますが、その日の最高価格を表示するにはどうすればいいですか?または平均価格ですか?

+0

私はPostgreSQLを好むでしょう。 – Vic

答えて

2

あなたはPostgresのdistinct on()演算子を使用することができますでprice descを含めることにより

SELECT distinct on (c.cust_id) c.cust_name, p.price, p.purchase_date 
from customer c 
    join purchase p ON c.cust_id = c.customer_id 
order by c.cust_id, p.date desc, p.price desc; 

order by 1日に2つの価格がある場合、Postgresは最高価格を選択します。

別のオプションは、(速いかもしれません)派生テーブル

select c.cust_id, c.cust_name, p.price, p.purchase_date 
from customer c 
    join (
    select distinct on (customer_id) customer_id, price, purchase_date 
    from purchase 
    order by customer_id, purchase_date desc, p.price desc 
) p on c.cust_id = p.customer_id; 
+0

答えをありがとう。この解決法( 'distinct on'を使用して)が、ウィンドウ関数を使用する以下のものとどのように比較されるか知っていますか? – Vic

+0

@ Vic:典型的には 'distinct on()'は、ウィンドウ関数を使った同等の解決法より高速です。ウィンドウ関数を使用すると、クエリの "distinct"の定義や、ネクタイの処理方法をより詳細に制御できます。 –

0

あなたが書いたネクタイの問題は、基本的なことから始めて、購入表に名前を付けておきましょう。これは単純な参加です:

SELECT c.name, p.price, p.date from purchase as p inner join customer as c 
ON c.cust_id = c.customer_id; 

これはあなたにすべての購入を含むテーブルを提供します。
今、この上のあなたは、たとえば、平均、合計、最大またはあなたが好きな凝集を追加することができます。

SELECT name, date, MAX(price) from (
    SELECT c.name, p.price, p.date from purchase as p inner join customer as c 
    ON c.cust_id = c.customer_id 
) group by name, date; 
+0

しかし、私はそれが最も最近の購入の価格だけを返すようにしたい。 – Vic

+0

それは最新の日付と価格を返しません(各日付の_highest_価格のみ) –

1

にレコードをランク​​付けするための標準的なSQLの道に参加することであるRANKまたはDENSE_RANK(両方とも結びつきを考える)またはROW_NUMBERである(ありません) 。

次のクエリは最後の購入日をとり、いくつかの購入がある場合は、より高い価格でレコードを選択します。 (同じ最高価格を持つ2つの購入があるもあれば、レコードの1つが任意に選択されますが、それは問題ではありません。)

select 
    customer.cust_name, 
    ranked.price 
from customer 
join 
(
    select 
    customer_id, 
    price, 
    row_number() over (partition by customer_id order by date desc, price desc) as rnk 
    from purchase_history 
) ranked on ranked.customer_id = customer.cust_id and ranked.rnk = 1; 

次のクエリは、前回の購入日の購入を取り、avarageを計算しますこれらの価格。

select 
    customer.cust_name, 
    avg(ranked.price) 
from customer 
join 
(
    select 
    customer_id, 
    price, 
    rank() over (partition by customer_id order by date desc) as rnk 
    from purchase_history 
) ranked on ranked.customer_id = customer.cust_id and ranked.rnk = 1 
group by customer.cust_id, customer.cust_name; 
+0

最後の行の 'customer.cust_id'は必要ですか? – Vic

+0

いいえ、同じ名前の顧客が2人いて、1つではなく2つの別々の行を取得する場合です。名前に固有の制約がある場合や気にしない場合は、これは必要ありません。 –

関連する問題