【问题标题】:Complex(?) SQL join query复杂(?)SQL连接查询
【发布时间】:2010-11-02 20:05:46
【问题描述】:

我有 2 张桌子:

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

2) 表格 Stockdata 包含表格中的股票数据 日期、符号、开盘价、最高价、最低价、收盘价、成交量(主键 = 日期、符号)

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

MDate,SDate,Symbol,Open,High,...

6/4/2001,6/4/2001,Foo,47,49,...

6/5/2001,null,null,null,null,...

6/6/2001,6/6/2001,Foo,54,56,...

MDate 来自 Masterdates,SDate 来自 Stockdata。我需要让输出从 Stockdata 中所需符号的第一个(最早)范围日期开始(在本例中为 Foo,从 2001 年 6 月 4 日开始),然后在 Masterdates 中包含所有日期,包括最后一个Stockdata 中所需符号的(最新)可用日期,在所述范围内的给定 Masterdate 记录没有对应 Stockdata 记录的情况下输出空值。

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

TIA

【问题讨论】:

  • 究竟是哪个 SQL 系统?微软 SQL 服务器? MySQL?

标签: sql


【解决方案1】:

在 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(date, symbol) 上有一个综合索引。

【讨论】:

  • 6GB 数据库上 22 秒。比我想象的要快,但不是我需要的地方。我认为如果我分解数据,我可以将其分解为更好的东西(目前我有每日、盘中、股票、期货、指数,你可以说,数据在一个表中)。谢谢!
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    这是一个经典的左连接:

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

    显然这应该被改进为只返回所需的列。

    【讨论】:

    • 但这会给我 Masterdates 中的一切,不是吗?
    【解决方案4】:

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

    【讨论】:

    • 你能解释一下吗?
    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 2018-02-08
    • 2011-10-08
    相关资源
    最近更新 更多