如何在select子句中使用join from子句(如SQLServer)执行Postgresql子查询?

如何在select子句中使用join from子句(如SQLServer)执行Postgresql子查询?,sql,sql-server,postgresql,subquery,Sql,Sql Server,Postgresql,Subquery,我试图在postgresql上编写以下查询: select name, author_id, count(1), (select count(1) from names as n2 where n2.id = n1.id and t2.author_id = t1.author_id ) from names as n1 group by name, author_id 这当然可以在Microsoft SQL Se

我试图在postgresql上编写以下查询:

select name, author_id, count(1), 
    (select count(1)
    from names as n2
    where n2.id = n1.id
        and t2.author_id = t1.author_id
    )               
from names as n1
group by name, author_id
这当然可以在Microsoft SQL Server上工作,但在postegresql上根本不起作用。我读了一些文档,似乎可以将其改写为:

select name, author_id, count(1), total                     
from names as n1, (select count(1) as total
    from names as n2
    where n2.id = n1.id
        and n2.author_id = t1.author_id
    ) as total
group by name, author_id
但这会在PostRegreSQL上返回以下错误:FROM中的子查询不能引用相同查询级别的其他关系。所以我被卡住了。有人知道我怎样才能做到吗


谢谢

我不确定我是否完全理解您的意图,但以下内容可能与您想要的内容非常接近:

select n1.name, n1.author_id, count_1, total_count
  from (select id, name, author_id, count(1) as count_1
          from names
          group by id, name, author_id) n1
inner join (select id, author_id, count(1) as total_count
              from names
              group by id, author_id) n2
  on (n2.id = n1.id and n2.author_id = n1.author_id)
不幸的是,这增加了按id以及姓名和作者id对第一个子查询进行分组的要求,我认为这是不需要的。不过,我不知道如何解决这个问题,因为您需要有可用的id才能加入第二个子查询。也许其他人会想出更好的解决办法


分享和享受。

我只是在这里用我在上面的评论中发布的基于Bob Jarvis answer的最终sql的格式化版本来回答:

select n1.name, n1.author_id, cast(count_1 as numeric)/total_count
  from (select id, name, author_id, count(1) as count_1
          from names
          group by id, name, author_id) n1
inner join (select author_id, count(1) as total_count
              from names
              group by author_id) n2
  on (n2.author_id = n1.author_id)

我知道这很旧,但由于有一个选项可以使用关键字LATERAL在连接内部使用相关子查询,因此问题中的查询如下所示:

SELECT 
    name, author_id, count(*), t.total
FROM
    names as n1
    INNER JOIN LATERAL (
        SELECT 
            count(*) as total
        FROM 
            names as n2
        WHERE 
            n2.id = n1.id
            AND n2.author_id = n1.author_id
    ) as t ON 1=1
GROUP BY 
    n1.name, n1.author_id
作为对@Bob Jarvis和@dmikam answer的补充,当您不使用模拟下方的横向时,Postgres不会执行良好的计划,在这两种情况下,查询数据结果是相同的,但成本非常不同

表结构

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);
在子查询中执行与GROUP BY的联接,而不执行横向

结果

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)
使用侧向

结果

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)
我的Postgres版本是PostgreSQL 10.3 Debian 10.3-1.pgdg90+1


如果更多的内部连接使用distinct,因为更多的连接组性能较慢

Perfect Bob,这确实有效。谢谢!我不得不做一点小小的改变,因为我不需要id的连接,只需要author\u id。所以最后的查询是:选择n1.name,n1.author\u id,count\u 1,total\u count from select id,name,author\u id,count1 as count\u 1 from names group by id,name,author\u id n1 internal join select author\u id,count1作为名称组中的total_count by author_id n2 on n2.author_id=n1.author_id现在我有了这个,我真正想要的是将count_1除以total_count,得到一个标准化的频率=Dops,刚刚意识到这里的sql格式不正确:我没有Ricado所说的问题,但是这个SQL完全解决了我的问题…:D谢谢你!!!实际上,这似乎应该适用于Postgres,但可能在6年前还没有:我想知道这两个查询的性能是否有差异,或者对于postgresql,这是不是相同的计划我做了这个测试,并感谢您提示使用侧向!!
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);
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)
select n1.name, n1.author_id, cast(count_1 as numeric)/total_count
  from (select id, name, author_id, count(1) as count_1
          from names
          group by id, name, author_id) n1
inner join (select distinct(author_id), count(1) as total_count
              from names) n2
  on (n2.author_id = n1.author_id)
Where true