避免SQL中重复子查询的最佳方法

避免SQL中重复子查询的最佳方法,sql,postgresql,query-optimization,Sql,Postgresql,Query Optimization,我有一个简单的两列表。例如,我们可以使用以下方法来构建数据: CREATE TABLE Duplicates (assignmentid varchar(5), questionid varchar(5)); INSERT INTO Duplicates (assignmentid, questionid) VALUES ('aaaaa', '11111'), ('aaaaa', '22222'), ('bbbbb', '22222'), ('bbbbb', '3333

我有一个简单的两列表。例如,我们可以使用以下方法来构建数据:

CREATE TABLE Duplicates
  (assignmentid varchar(5), questionid varchar(5));

INSERT INTO Duplicates
  (assignmentid, questionid)
VALUES
  ('aaaaa', '11111'),
  ('aaaaa', '22222'),
  ('bbbbb', '22222'),
  ('bbbbb', '33333'),
  ('bbbbb', '33333');
有两行是相同的。还有一个问题出现在多个作业上。后者是一个有效的场景,我正在尝试查询多个作业中的所有问题。因此,我期望的输出是:

  aaaaa, 22222
  bbbbb, 22222
我能够通过以下方法得到这个结果:

SELECT main.questionid, sub.assignmentid 
FROM (
   SELECT questionid, count(assignmentid) AS AssignmentCount 
   FROM ( 
      SELECT DISTINCT questionid, assignmentid 
      FROM Duplicates
   ) sub 
   GROUP BY questionid
   HAVING AssignmentCount > 1
) main
INNER JOIN (
     SELECT DISTINCT questionid, assignmentid 
     FROM Duplicates
) sub ON main.questionid = sub.questionid;

如您所见,独特的子查询重复了两次。我可以通过使用WITH命令来避免这种情况,但我的理解是,这并不一定意味着子查询只执行一次。现在我来到StackOverflow,询问是否有人知道一种更有效的方式来运行这个查询

只需使用窗口函数即可。一种方法是将答案数与不同答案数进行比较:

select distinct answerid, questionid
from (select d.*,
             count(distinct answerid) over (partition by questionid) as cntd,
             count(*) over (partition by questionid) as cnt
      from duplicates d
     ) d
where cntd <> cnt;

这将使用行号进行不同的计算。

您可以将其简化为:

select *
from duplicates
where questionid in (select questionid
                     from duplicates
                     group by questionid
                     having count(distinct assignmentid) > 1);

子查询返回分配给多个assignmentid的所有QuestionId

CTE(“with”)查询将执行一次。@没有名称的马请在CTE注释上展开。我认为CTE应该被视为视图(而不是临时表),这意味着每次使用视图时,都会重复对底层表的调用。也许我误解了。下面是我提到的另一个stackoverflow页面的链接:不幸的是,Postgres不支持窗口中的
distinct
functions@a_horse_with_no_name . . . 非常感谢。我很方便地忘记了SQL Server不是唯一存在此缺陷的数据库。
select *
from duplicates
where questionid in (select questionid
                     from duplicates
                     group by questionid
                     having count(distinct assignmentid) > 1);