Головоломка SQL join - PullRequest
       8

Головоломка SQL join

1 голос
/ 09 октября 2009

С учетом

pricetable  
sym(k)   pricedate(k) price
msft     1/2/2009     33
msft     1/3/2009     34
msft     1/4/2009     35
ibm   1/2/2009       66
ibm   1/3/2009       65
ibm   1/4/2009       64

и

datestable
pricedate(k)
1/1/2009
1/2/2009
1/3/2009
1/4/2009

Я хотел бы получить этот набор результатов

sym pricedate price
msft 1/1/2009 null
msft 1/2/2009 33
msft 1/3/2009 34
msft 1/4/2009 35
ibm  1/1/2009  null
ibm  1/2/2009  66
ibm  1/3/2009  65
ibm  1/4/2009  64

Это одноразовый дамп, поэтому я не против создания промежуточных временных таблиц, если это будет сделано.

FWIW, я не просто выкидываю эту проблему на SO, я перепробовал кучу вещей, но не могу заставить ее работать.

ТИА

Ответы [ 5 ]

3 голосов
/ 09 октября 2009
SELECT b.sym, b.pricedate, p.price 
FROM 
(
    SELECT DISTINCT sym, pricedate
    FROM pricetable CROSS JOIN datestable
) b  /* base table */
LEFT JOIN pricetable p ON p.sym = b.sym AND p.pricedate = b.pricedate
ORDER BY b.pricedate, b.sym
2 голосов
/ 09 октября 2009
 SELECT syms.sym, pt.pricedate, syms.price FROM
 (SELECT DISTINCT sym, datestable.priceDate FROM priceTable, datestable) syms 
     LEFT JOIN priceTable pt on pt.priceDate = syms.priceDate

должен это сделать.

По крайней мере, он работает под SQL Server.

1 голос
/ 09 октября 2009

Это похоже на работу:

DECLARE @pricetable TABLE (sym VARCHAR(10), pricedate DATETIME, price INT)
INSERT INTO @pricetable (sym, pricedate, price) VALUES('msft', '1/2/9', 33)
INSERT INTO @pricetable (sym, pricedate, price) VALUES('msft', '1/3/9', 34)
INSERT INTO @pricetable (sym, pricedate, price) VALUES('msft', '1/4/9', 35)
INSERT INTO @pricetable (sym, pricedate, price) VALUES('ibm', '1/2/9', 66)
INSERT INTO @pricetable (sym, pricedate, price) VALUES('ibm', '1/3/9', 65)
INSERT INTO @pricetable (sym, pricedate, price) VALUES('ibm', '1/4/9', 64)

DECLARE @datestable TABLE (pricedate DATETIME)
INSERT INTO @datestable (pricedate) VALUES('1/1/9')
INSERT INTO @datestable (pricedate) VALUES('1/2/9')
INSERT INTO @datestable (pricedate) VALUES('1/3/9')
INSERT INTO @datestable (pricedate) VALUES('1/4/9')


SELECT AllDates.sym, AllDates.pricedate, outerp.price
    FROM 
        (
            SELECT 
                d.pricedate, 
                p.sym
            FROM 
                @datestable AS d 
                CROSS JOIN @pricetable AS p
            GROUP BY 
                d.pricedate, 
                p.sym
        ) AllDates
        LEFT OUTER JOIN @pricetable AS outerp ON
            outerp.pricedate = AllDates.pricedate
            AND outerp.sym = AllDates.sym
ORDER BY AllDates.sym, AllDates.pricedate

Результаты:

sym        pricedate               price
---------- ----------------------- -----------
ibm        2009-01-01 00:00:00.000 NULL
ibm        2009-01-02 00:00:00.000 66
ibm        2009-01-03 00:00:00.000 65
ibm        2009-01-04 00:00:00.000 64
msft       2009-01-01 00:00:00.000 NULL
msft       2009-01-02 00:00:00.000 33
msft       2009-01-03 00:00:00.000 34
msft       2009-01-04 00:00:00.000 35
1 голос
/ 09 октября 2009

Не проверено ... ключевое наблюдение, вам, кажется, нужна строка для каждой акции для каждого возможного дня.

SELECT k1.sym, k1,pricedate, k1.price
  FROM DatesTable JOIN (SELECT DISTINCT(sym) FROM PriceTable) AS k1 ON 1 = 1
       LEFT JOIN Pricetable AS pt
                 ON (k1.pricedate = pt.pricedate AND k1.sym = pt.sym)
 ORDER BY k1.sym DESC, k1.pricedate;

Альтернативой 'JOIN ... ON 1 = 1' является 'CROSS JOIN':

SELECT k1.sym, k1,pricedate, k1.price
  FROM DatesTable CROSS JOIN (SELECT DISTINCT(sym) FROM PriceTable) AS k1
       LEFT JOIN Pricetable AS pt
                 ON (k1.pricedate = pt.pricedate AND k1.sym = pt.sym)
 ORDER BY k1.sym DESC, k1.pricedate;
0 голосов
/ 09 октября 2009

Вы пробовали

select a.sym, a.pricedate, p2.price
(select distinct p.sym, d.pricedate
from pricetable p
cross join
datestable d )a
left join pricetable p2
on a.sym = p2.sym and a.pricedate = p2.pricedate

или

выберите a.sym, a.pricedate, p2.price (выберите p.sym, d.pricedate от (выберите отличный символ из таблицы цен) перекрестное соединение Сроки d) осталось присоединиться к прайс-листу p2 на a.sym = p2.sym и a.pricedate = p2.pricedate

перекрестное объединение должно получить полный список символов и дат, затем, оставив соединение с таблицей цен снова, вы получите остальные данные столбца для тех записей, которые имеют цену.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...