2009-10-08 2 views
1

УчитываяSQL присоединиться к головоломке

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 Я не просто сбрасываю эту проблему на СО, я пробовал кучу вещей, но не могу заставить ее работать.

ТИА

ответ

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

Да, вот и все! – user119282

+0

Забавный - ORDER BY кажется обратным от результатов, показанных в вопросе, и ему также кажется, что нужно b.sym DESC! :) –

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

+2

'' присоединиться к нотацию? тьфу. –

+0

Эх, это как я думаю о крест-соединениях в sql-сервере. – Dana

1

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

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

Вы пробовали

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 from (выберите выделение sym fr О.М. pricetable) крест р присоединиться datestable г) влево присоединиться pricetable p2 на a.sym = p2.sym и a.pricedate = p2.pricedate

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

+0

Мы должны надеяться, что оптимизатор подталкивает SELECT DISTINCT до PriceTable, прежде чем делать CROSS JOIN, чтобы избежать большой промежуточной таблицы. –

+0

Ну, может, и так. – HLGEM

1

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

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 
Смежные вопросы