简体   繁体   中英

Query all columns of table1 left join and count of the table2

I couldn't get this query working :

DOESN'T WORK

select 
    Region.*, count(secteur.*) count 
from  
    Region 
left join 
    secteur on secteur.region_id = Region.id

The solution I found is this but is there a better solution using joins or if this doesn't affect performance, because I have a very large dataset of about 500K rows

WORKS BUT AFRAID OF PERFORMANCE ISSUES

select 
    Region.*,
    (select count(*) 
     from Secteur 
     where Secteur.Region_id = region.id) count 
from  
    Region 

I would suggest:

select region.*, count(secteur.region_id) as count
from region left join secteur on region.id = secteur.region_id
group by region.id, region.field2, region.field3....

Note that count(table.field) will ignore nulls, whereas count(*) will include them.


Alternatively, left join on a subquery and use coalesce to avoid nulls:

select region.*, coalesce(t.c, 0) as count
from region left join 
(select region_id, count(*) as c from secteur group by region_id) t on region.id = t.region_id

I'd join region on an aggregate query of secteur :

SELECT    r.*, COALESCE(s.cnt, 0)
FROM      region r
LEFT JOIN (SELECT   region_id, COUNT(*) AS cnt
           FROM     secteur
           GROUP BY region_id) s ON s.region_id = r.id

I would go with this query:

select r.*,
       (select count(*) 
        from Secteur s
        where s.Region_id = r.id
      ) as num_secteurs 
from Region r;

Then fix the performance problem by adding an index on Secteur(region_id) :

create index idx_secteur_region on secteur(region_id);

You make a two mistakes

  • First: you have try to calulate COUNT() in only one (I mean, the second) table. This doesn't will work because theCOUNT(), like an any aggregate function, calculates only for the whole set of rows , not just for any part of the set (not only just for the one or an other joined table).
    In your first query, you may replace secteur. * only by asterisk, like a Region.region_id, count(*) AS count , and do not forget add Region.region_id on the GROUP BY step.
  • Second: You has define not only aggregate function in the query, but and other fields: select Region.* , but you don't define them in GROUP BY step. You need to add to GROUP BY statement all columns, which you has define in the SELECT step but not apply an aggregate functions to them.
  • Append: not, GROUP BY Region.* doesn't will work, you should to define a columns in the GROUP BY step by their actual names.

So, correct form of this will looks like a

SELECT 
    Region.col1
    ,Region.col2,
    , count(*) count 
from  Region 
left join 
    secteur on secteur.region_id = Region.id
GROUP BY Region.col1, Region.col2

Or, if you don't want to type each name of column, use window queries

SELECT
    Region.*,
    , count( * ) OVER (PARTITION BY region_id) AS count 
from  Region 
left join 
    secteur on secteur.region_id = Region.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