复杂(?)SQL连接查询

时间:2009-06-14 14:39:28

标签: sql

我有两张桌子:

1)表Masterdates,包含自1900年1月1日以来的所有日期

2)表格Stockdata包含表格中的股票数据    日期,符号,打开,高,低,关闭,音量(主键=日期,符号)

这是我想要检索的内容(以CSV格式显示)

MDate,SDATE,符号,开放,高,...

四分之六/ 2001,6 / 4/2001年,富,47,49,...

6/5/2001年,NULL,NULL,NULL,NULL,...

6/6 / 2001,6 / 6/2001年,富,54,56,...

其中MDate来自Masterdates,而SDate来自Stockdata。我需要让输出从Stockdata中所需符号的第一个(最早的)范围日期开始(在此示例中,Foo,从6/4/2001开始),然后包括Masterdates中的所有日期,包括最后一个日期(最新)Stockdata中所需符号的可用日期,输出空值,其中对于给定的Masterdate记录,在所描述的范围内没有相应的Stockdata记录。

有没有办法在单个查询,一系列查询和/或添加辅助表中执行此操作,这将产生快速结果?或者我是否必须转出我想要的超集,然后使用我的(非SQL)编程语言构造最终输出?

TIA

4 个答案:

答案 0 :(得分:7)

在SQLITE3中测试,您的数据库实现可能会有所不同

SELECT   m.date, 
         s.symbol, 
         s.open, 
         s.high, 
         s.low, 
         s.close, 
         s.volume
FROM     masterdate AS m LEFT OUTER JOIN 
         stockdata AS s ON m.date = s.date
AND      s.symbol = 'Foo'
WHERE    m.date >= (SELECT MIN(date) FROM stockdata WHERE symbol = 'Foo')
AND      m.date <= (SELECT MAX(date) FROM stockdata WHERE symbol = 'Foo')

如果这样做不够快,那么你可以通过在一个查询中设置最小值和最大值的变量然后在主查询中使用这些变量来提高性能。这样可以为您节省至少一个索引。

所以(在SQL Server语法中)

SET @symbol = 'Foo'

SELECT @mindate = MIN(date),
       @maxdate = MAX(date)
FROM   stockdata
WHERE  stockdata.symbol = @symbol


SELECT   m.date, 
         s.symbol, 
         s.open, 
         s.high, 
         s.low, 
         s.close, 
         s.volume
FROM     masterdate AS m LEFT OUTER JOIN 
         stockdata AS s ON m.date = s.date
AND      s.symbol = @symbol
WHERE    m.date BETWEEN @mindate AND @maxdate

您还需要确保masterdate.date上有索引,stockdata(日期,符号)上有复合索引。

答案 1 :(得分:3)

这是一个经典的左连接:

SELECT * FROM masterdates
    LEFT JOIN stockdata ON masterdates.date = stockdata.date;

显然,应该将其改进为仅返回所需的列。

答案 2 :(得分:1)

如果使用SQLServer,则可以使用TSQL存储过程来获取结果。它基本上有两行:

1)获取可用数据的第一个日期 2)具有外连接的查询

如果您使用Oracle,您可以使用PL / SQL编写类似(虽然有点复杂)的存储过程来计算您想要的答案。

答案 3 :(得分:0)

我建议填写Stockdata表中缺少的条目并使用内部联接。应该快得多。