PostgreSQL: как написать запрос с помощью объединений? - PullRequest
1 голос
/ 09 ноября 2011

Как бы я написал этот запрос с помощью объединений? Я пытался сделать это, но это не работает.

select fund.fundname, sum(shares) as tt, (sum(shares)*price.price) as value 
from trans, fund, customer, price 
where trans.fundid = fund.fundid 
and trans.transdate = '2009-1-1' 
and price.fundid = trans.fundid 
and price.pricedate = trans.transdate 
and trans.sin = customer.sin 
and customer.name = 'Jacob' 
group by fund.fundname, price.price;

Спасибо

Ответы [ 4 ]

1 голос
/ 09 ноября 2011

Еще одно:

SELECT f.fundname
      ,sum(shares) AS tt
      ,(sum(shares) * p.price) AS value 
FROM   trans t
JOIN   fund f USING (fundid)
JOIN   price p ON (p.fundid, p.pricedate) = (t.fundid, t.transdate)
JOIN   customer c USING (sin)
WHERE  t.transdate = '2009-1-1' 
AND    c.name = 'Jacob' 
GROUP  BY 1, p.price;

Я использовал несколько синтаксических упрощений:

  • USING, если левый и правый имеют одно и то же имя.Осторожно, если имя всплывает несколько раз, то порядок СОЕДИНЕНИЙ имеет значение, или он может стать неоднозначным.Пример здесь: sin.Если есть также fund.sin, вы должны использовать вместо него явный JOIN ON.

  • (p.fundid, p.pricedate) = (t.fundid, t.transdate) - это сокращение от
    (p.fundid = t.fundid AND p.pricedate = t.transdate)

  • GROUP BY 1 коротко для
    GROUP BY <fist column in the select list>

Подробнее об объединениях в руководстве здесь .

1 голос
/ 09 ноября 2011

Вам просто нужно разделить условия объединения и условия фильтрации:

SELECT fund.fundname, SUM(shares) AS tt, SUM(shares) * price.price AS value
FROM trans
INNER JOIN fund
    USING (fundid)
INNER JOIN price
    ON price.fundid = trans.fundid
   AND price.pricedate = trans.transdate
INNER JOIN customer
    USING (sin)
WHERE transdate = '2009-1-1'
  AND customer.name = 'Jacob'
GROUP BY fund.fundname, price.price

Обратите внимание, что USING "объединит" два столбца, поэтому вам не нужно использовать псевдонимы.

1 голос
/ 09 ноября 2011
 select fund.fundname, sum(shares) as tt, (sum(shares)*price.price) as value 
 from trans 
 join fund on fund.fundid=trans.fundid 
 join customer on customer.sin=trans.sin 
 join price on price.pricedate=trans.transdate
 where  
 trans.transdate = '2009-1-1' 
 and customer.name = 'Jacob' 
 group by fund.fundname, price.price;
1 голос
/ 09 ноября 2011

Полагаю, вы говорите о явных соединениях.Как вы понимаете, объединения просто неявные.Вы бы сделали это так:

SELECT fund.fundname, sum(shares) as tt, (sum(shares)*price.price) as value 
FROM trans
JOIN fund
 ON ( trans.fundid = fund.fundid )
JOIN customer
 ON ( trans.sin = customer.sin )
JOIN price 
 ON ( price.fundid = trans.fundid )
WHERE trans.transdate = '2009-1-1' 
 AND price.pricedate = trans.transdate 
 AND customer.name = 'Jacob' 
GROUP BY fund.fundname, price.price;

Postgresql также допускает изящные сокращения с USING, которые будут включать только одну копию столбца в конечный набор результатов:

SELECT fundname, sum(shares) as tt, (sum(shares)*price.price) as value 
FROM trans
JOIN fund
 USING ( fundid )
JOIN customer
 USING ( sin )
JOIN price 
 USING ( fundid )
WHERE trans.transdate = '2009-1-1' 
 AND price.pricedate = trans.transdate 
 AND customer.name = 'Jacob' 
GROUP BY fund.fundname, price.price;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...