6

3つのテーブルを持つデータベースがあります。

  • エクイティ
  • ストックスプリット
  • 配当

株式と株式分割の間、および株式と配当の間には1対多の関係があります。各エクイティについて、株式分割と配当の数を示したいと思います。

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にインデックスが存在すると想定します。

4

3 に答える 3

12

*の代わりに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
于 2012-07-02T18:01:51.400 に答える
2

これが元のクエリです

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をシミュレートします。
于 2012-07-02T16:48:56.793 に答える
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
于 2014-01-12T05:01:14.417 に答える