2016-08-18 15 views
1

私は今日、postgresqlを使って何か変わった動作をしました。言い換えればSQL LEFT JOINは左のテーブルの列を空にします

129 | | | 
195 | | | 
251 | | | 
... 

は、テーブルactual_pricesの列が空である:

WITH actual_prices AS (
    -- Looking for prices from now to the given number of days back 
    SELECT * 
    FROM prices 
    WHERE price_date >= now()::date - 93 
) 
, distinct_products_sold AS (
    SELECT distinct(id_product) as pid FROM products_sold 
) 
, first_prices AS (
    SELECT s.pid, p.product_id, p.price_date, p.price 
    FROM distinct_products_sold s 
    LEFT JOIN actual_prices p ON p.product_id = s.pid 
) 
select * from first_prices; 

このコードは、この種のものを出力します。私はJOINをちょっと調べてみました。LEFT JOINの代わりにRIGHT JOINを入力すると、distinct_products_soldの列は空になりますが、actual_pricesの列は正しく表示されます。何が原因でしょうか?

+1

Distinctは(列上の)関数ではなく、SELECT DISTINCTの一部であり、選択された行全体で機能します。 'SELECT distinct(id_product)...'は 'SELECT DISTINCT id_product ... 'と同じです。 – jarlh

+1

なぜそれは変だ? 'p.product_id = s.pid'のどちらのテーブルでも、おそらく一致する行はありません。 – GarethD

+0

結合の性質は、「空の」結合が記録されることです。 'LEFT JOIN'の場合、結合の左側のレコードは一致するものがなくてもすべて保持され、' RIGHT JOIN'の場合は真です。 –

答えて

2

あなたは間違った方向を持っています。外部結合によってデータが1つのテーブルから失われるのではなく、欠落している列をヌルで埋めてテーブル間に結合を強制します。

WITH P (PID) AS 
(
SELECT * 
    FROM (
     VALUES (1), (2), (3) 
     ) AS T (C) 
), 
Q (QID) AS 
(
SELECT * 
    FROM (
     VALUES (4), (5), (6) 
     ) AS T (C) 
) 
SELECT p.PID, q.QID 
    FROM P p, Q q 
WHERE p.PID = q.QID 
UNION 
SELECT p.PID, NULL 
    FROM P p 
WHERE p.PID NOT IN (SELECT QID FROM Q); 
-1

ここWITH句のための必要はありません、これを試してみてください:テーブルpricesからすべての列がまだNULLの場合

SELECT t.pid , p.product_id, p.price_date, p.price 
FROM (SELECT distinct id_product as pid FROM products_sold) t 
LEFT JOIN prices p 
ON(t.pid = p.product_id AND p.price_date >= now()::date - 93) 

が、その後、ちょうど一致するデータが存在しない場合。

左結合では、先頭のテーブル(左テーブル)からのすべてのレコードと、右テーブルからの一致したデータのみが保持されます。

+0

@Downvoterは説明してくれませんか? – sagi

0

私の脳裏を許してください。比類のない結果を出力します(驚くほど)。 LEFT/RIGHTジョインは、左右のテーブルの不一致結果も出力します。

P.S.質問を投稿する前に立ち上げをしてください。

関連する問題