SQL加入益智游戏

时间:2009-10-08 20:31:41

标签: sql join

鉴于

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上,我尝试了很多东西,但是无法让它发挥作用。

TIA

5 个答案:

答案 0 :(得分: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

答案 1 :(得分: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 :(得分: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;

答案 3 :(得分: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

答案 4 :(得分: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(从pricetable中选择不同的sym)p     交叉加入     datestable d)a     左连接pricetable p2     在a.sym = p2.sym和a.pricedate = p2.pricedate

交叉连接应该得到一个完整的syms和日期列表,然后再次加入价格表,你应该得到那些有价格的记录的其余列数据。