简体   繁体   中英

How to make an efficient Count of rows from another table (join)

I have a database of 100,000 names in cemeteries. The cemeteries number around 6000....i wish to return the number of names in each cemetery..

If i do an individual query, it takes a millisecond

SELECT COUNT(*) FROM tblnames
    WHERE tblcemetery_ID = 2 

My actual query goes on and on and I end up killing it so I dont kill our database. Can someone point me at a more efficient method?

select tblcemetery.id,
  (SELECT COUNT(*) FROM tblnames
        WHERE tblcemetery_ID = tblcemetery.id) AS casualtyCount
    from tblcemetery                                                      
      ORDER BY
   fldcemetery

You can rephrase your query to use a join instead of a correlated subquery:

SELECT
    t1.id,
    COUNT(t2.tblcemetery_ID) AS casualtyCount
FROM tblcemetery t1
LEFT JOIN tblnames t2
    ON t1.id = t2.tblcemetery_ID
GROUP BY
    t1.id
ORDER BY
    t1.id

I have heard that in certain databases, such as Oracle, the optimizer is smart enough to figure out what I wrote above, and would refactor your query under the hood. But the MySQL optimizer might not be smart enough to do this.

One nice side effect of this refactor is that we now see an opportunity to improve performance even more, by adding indices to the join columns. I am assuming that id is the primary key of tblcemetery , in which case it is already indexed. But you could add an index to tblcemetery_ID in the tblnames table for a possible performance boost:

CREATE INDEX cmtry_idx ON tblnames (tblcemetery_ID)

Or you could look up group by here fe and do something like

   SELECT tblcemetery_ID,  sum(1) from tblnames group by tblscemetery_id

You essentially sum up 1 for each name entry that belongs to this cemetery as you are not interessted in the names at all, no need to join to the cemetary detail table

Not sure if sum(1) or count(*) is better, both should work.

Youll only get cemetaries that have ppl inside though

It could even be done without a JOIN by using an EXISTS clause like this

SELECT id, COUNT(*) AS casualtyCount
FROM tblcemetery
WHERE EXISTS (SELECT 1 FROM tblnames WHERE tblcemetery_ID=id)
GROUP BY id
ORDER BY id

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM