2012-07-02 26 views
1

我有3個表數據庫:MySQL的數子查詢

  • 股票
  • stocksplits
  • 分紅

有一個股票和stocksplits之間一對多的關係,與股票之間和股息。對於每一個股票我想顯示stocksplits和分紅的數量:

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上。

+1

我相信你錯過了查詢的後半部分 –

+0

@lc:fixed,謝謝。 – Jimmy

+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))

  • 如果LEFT JOIN在右側表上沒有對應的條目,則IFNULL將把NULL變成0。
  • 如果LEFT JOIN了右側進入,IF函數返回1
  • 如果LEFT JOIN沒有右側進入,IF函數返回0
  • SUM加起來所有的1和0,模擬COUNT
+0

我喜歡超速(我的查詢確實感覺效率低下);然而,你建議的查詢似乎不起作用(它會返回至少1的一切?) – Jimmy

+0

另外,如果左連接不在子查詢中?假設我想添加另一列,股息數量(又是另一個與股票表有一對多關係的表)......它需要自己的左連接? – Jimmy

+0

我已經修改了這個問題,以幫助爲我的評論重新設置上下文:添加另一列。 – Jimmy

8

計數的的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 
0

在我的先進經驗,MySQL的correlated subquery有表現不佳。

Q1 - JOIN

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