I have a database with 3 tables:
There is a one to many relationship between equities and stocksplits, and between equities and dividends. For each equity I would like to show the number of stocksplits and dividends:
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
The query appears to run fine, though I suspect it is inefficient. How can it be refactored to be faster? No DBMS (SQL query via .net to MySQL server), assume indices exist on the primary ID of each table.
No. If a subquery involves aggregates such as COUNT(*) or GROUP BY - and the aggregates are used as part of the qualification of the overall query - you don't, in general, have the syntax available to state it as a simple join.
MySQL COUNT() Function The COUNT() function returns the number of records returned by a select query.
SQL SELECT COUNT(*) function SQL SELECT statement can be used along with COUNT(*) function to count and display the data values. The COUNT(*) function represents the count of all rows present in the table (including the NULL and NON-NULL values).
COUNT() with HAVINGThe HAVING clause with SQL COUNT() function can be used to set a condition with the select statement. The HAVING clause is used instead of WHERE clause with SQL COUNT() function.
Counting the PKs instead of * might already help:
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
Here is your original query
SELECT equities.Symbol,
(SELECT COUNT(*)
FROM stocksplits
WHERE stocksplits.EquityID = equities.InstrumentID) as `# Splits`
FROM equities
I was just thinking that an LEFT JOIN
would be cleaner
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;
The IFNULL covers any stock that had no stock splits
Give it a Try and see it it runs faster
Let me explain the expression SUM(IF(IFNULL(stocksplits.EquityID,0)=0,0,1))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With