我有一个包含3个表的数据库:
股票和股票之间以及股票和股息之间存在一对多的关系。对于每个股权,我想显示股票分割和股息的数量:
SELECT equities.Symbol,
(SELECT COUNT(*)
FROM stocksplits
WHERE stocksplits.EquityID = equities.InstrumentID) as `# Splits`,
(SELECT COUNT(*)
FROM dividends
WHERE dividends.EquityID = equities.InstrumentID) as `# Dividends`
FROM equities
查询似乎运行正常,但我怀疑它效率低下。怎样才能更快地重构?没有DBMS(通过.net到MySQL服务器的SQL查询),假设索引存在于每个表的主ID上。
答案 0 :(得分:9)
计算PK而不是*可能已经有所帮助:
SELECT equities.Symbol,
(SELECT COUNT(stocksplitsID)
FROM stocksplits
WHERE stocksplits.EquityID = equity.InstrumentID) as `# Splits`,
(SELECT COUNT(dividendsid)
FROM dividends
WHERE dividends.EquityID = equities.InstrumentID) as `# Dividends`
FROM equities
答案 1 :(得分:1)
这是您的原始查询
SELECT equities.Symbol,
(SELECT COUNT(*)
FROM stocksplits
WHERE stocksplits.EquityID = equities.InstrumentID) as `# Splits`
FROM equities
我只是认为LEFT JOIN
会更清洁
SELECT equities.Symbol,
SUM(IF(IFNULL(stocksplits.EquityID,0)=0,0,1)) StockSplits,
SUM(IF(IFNULL(dividends.EquityID ,0)=0,0,1)) Dividends
FROM
equities
LEFT JOIN stocksplits ON equities.InstrumentID = stocksplits.EquityID
LEFT JOIN dividends ON equities.InstrumentID = dividends.EquityID
GROUP BY equities.Symbol;
IFNULL涵盖任何没有股票分裂的股票
尝试一下,看看它运行得更快
让我解释一下SUM(IF(IFNULL(stocksplits.EquityID,0)=0,0,1))
答案 2 :(得分:0)
在我的经验中,MySQL的correlated subquery
表现不佳。
Q1 - 加入
SELECT t1.Symbol, t1.cnt_splits, t2.cnt_dividends
FROM (
SELECT equities.Symbol AS Symbol, COUNT(*) AS cnt_splits
FROM equities LEFT JOIN stocksplits
ON stocksplits.EquityID = equities.InstrumentID
GROUP BY equities.Symbol
) t1,
(
SELECT equities.Symbol AS Symbol, COUNT(*) AS cnt_dividends
FROM equities LEFT JOIN dividends
dividends.EquityID = equities.InstrumentID
GROUP BY equities.Symbol
) t2 ON t1.Symbol = t2.Symbol;
Q2 - UNION
Q1
没有correlate subquery
并产生与您相同的结果。但需要额外的连接,这需要时间。以下UNION
模式更快,但输出应在客户端转换。
SELECT equities.Symbol AS Symbol, COUNT(*) AS cnt_splits
FROM equities LEFT JOIN stocksplits
ON stocksplits.EquityID = equities.InstrumentID
GROUP BY equities.Symbol
UNION
SELECT equities.Symbol AS Symbol, COUNT(*) AS cnt_dividends
FROM equities LEFT JOIN dividends
dividends.EquityID = equities.InstrumentID
GROUP BY equities.Symbol