How to do a Postgresql subquery in select clause with join in from clause like SQL Server?

前端 未结 5 1966
野性不改
野性不改 2021-01-30 04:00

I am trying to write the following query on postgresql:

select name, author_id, count(1), 
    (select count(1)
    from names as n2
    where n2.id = n1.id
             


        
5条回答
  •  北海茫月
    2021-01-30 04:14

    Complementing @Bob Jarvis and @dmikam answer, Postgres don't perform a good plan when you don't use LATERAL, below a simulation, in both cases the query data results are the same, but the cost are very different

    Table structure

    CREATE TABLE ITEMS (
        N INTEGER NOT NULL,
        S TEXT NOT NULL
    );
    
    INSERT INTO ITEMS
      SELECT
        (random()*1000000)::integer AS n,
        md5(random()::text) AS s
      FROM
        generate_series(1,1000000);
    
    CREATE INDEX N_INDEX ON ITEMS(N);
    

    Performing JOIN with GROUP BY in subquery without LATERAL

    EXPLAIN 
    SELECT 
        I.*
    FROM ITEMS I
    INNER JOIN (
        SELECT 
            COUNT(1), n
        FROM ITEMS
        GROUP BY N
    ) I2 ON I2.N = I.N
    WHERE I.N IN (243477, 997947);
    

    The results

    Merge Join  (cost=0.87..637500.40 rows=23 width=37)
      Merge Cond: (i.n = items.n)
      ->  Index Scan using n_index on items i  (cost=0.43..101.28 rows=23 width=37)
            Index Cond: (n = ANY ('{243477,997947}'::integer[]))
      ->  GroupAggregate  (cost=0.43..626631.11 rows=861418 width=12)
            Group Key: items.n
            ->  Index Only Scan using n_index on items  (cost=0.43..593016.93 rows=10000000 width=4)
    

    Using LATERAL

    EXPLAIN 
    SELECT 
        I.*
    FROM ITEMS I
    INNER JOIN LATERAL (
        SELECT 
            COUNT(1), n
        FROM ITEMS
        WHERE N = I.N
        GROUP BY N
    ) I2 ON 1=1 --I2.N = I.N
    WHERE I.N IN (243477, 997947);
    

    Results

    Nested Loop  (cost=9.49..1319.97 rows=276 width=37)
      ->  Bitmap Heap Scan on items i  (cost=9.06..100.20 rows=23 width=37)
            Recheck Cond: (n = ANY ('{243477,997947}'::integer[]))
            ->  Bitmap Index Scan on n_index  (cost=0.00..9.05 rows=23 width=0)
                  Index Cond: (n = ANY ('{243477,997947}'::integer[]))
      ->  GroupAggregate  (cost=0.43..52.79 rows=12 width=12)
            Group Key: items.n
            ->  Index Only Scan using n_index on items  (cost=0.43..52.64 rows=12 width=4)
                  Index Cond: (n = i.n)
    

    My Postgres version is PostgreSQL 10.3 (Debian 10.3-1.pgdg90+1)

提交回复
热议问题