Sql server 从不同的两列中选择所有列

Sql server 从不同的两列中选择所有列,sql-server,group-by,unique,distinct,Sql Server,Group By,Unique,Distinct,我需要在以下数据库中选择具有不同'CP'的*where distinct'Rua': id Rua Local Conc CP 81143 dos moinhos Rio Tinto Gondomar 0123 81142 dos Moinhos Rio Tinto Gondomar 4435 81141 dos Moinhos

我需要在以下数据库中选择具有不同
'CP'
的*where distinct
'Rua'

id      Rua                  Local           Conc       CP
81143   dos moinhos          Rio Tinto       Gondomar   0123
81142   dos Moinhos          Rio Tinto       Gondomar   4435
81141   dos Moinhos          Rio Tinto       Gondomar   4435
通过以下查询,我可以获得两列:

SELECT Rua, CP 
FROM  Codigo
GROUP BY Rua, CP
HAVING COUNT(*) = 1
但是我想要所有的专栏<代码>选择*返回“列'Codigo.id'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。”

所以我找到了这个答案:

我没有选择接受的答案,因为我需要一个快速查询(这将用于AJAX搜索建议)。我用了另一个投票率很高的答案。因此,我创建了以下查询:

SELECT * From Codigo
WHERE  (Rua,CP) IN (
   SELECT Rua, CP
   FROM   Codigo
   GROUP  BY Rua, CP
   HAVING COUNT(*) = 1 
);
返回在预期条件的上下文中指定的非布尔类型的表达式,接近“,”错误。为什么它期望
WHERE
之后的
Rua
为布尔值?在回答中,他们使用了
saleprice
,这似乎不是布尔值


因此,我的问题是如何选择所有,包括具有相同
Rua
CP
的行,但这些行只能选择一次(
DISTINCT
)?

SQL Server不支持(val1,val2)语法中的
(a,b)

使用
EXISTS
检查该对

SELECT *
FROM   Codigo C1
WHERE  EXISTS (SELECT 1
               FROM   Codigo C2
               WHERE  C1.Rua = C2.Rua
                      AND C1.CP = C2.CP
               HAVING Count(*) = 1); 
或者使用
COUNT()Over()
窗口聚合函数对每个
Rua、CP
组合的记录进行计数,并筛选计数为
1的组,以在每个不同的
CP
中查找一行
Rua

SELECT *
FROM   (SELECT *,
               Count(1)OVER(partition BY Rua, CP) AS cnt
        FROM   Codigo C1) A
WHERE  cnt = 1 
这将是我的首选方法,因为它比使用
EXISTS
高效得多,优化器只需扫描/查找表一次

如果不希望重复记录,请使用
行号()

我已使用
Id
列订购了重复记录,并从重复记录中选择了第一条记录

使用窗口功能(单表读取):

使用EXISTS(读取表两次):

加入(再次加入两次):


两者都有效。第一个建议需要33秒,第二个建议需要3秒:)为什么会有这么大的差异?@Dillinger-因为优化器每秒钟只需要扫描/查找一次表。我想我没有正确地提出这个问题。我希望包含具有相同
Rua
CP
的行,但只包含一次。这样,我只得到没有重复的
Rua
CP
的结果。如果我编辑并修正我的问题,你会修正你的答案吗?@Dillinger-是的,当然。
存在中按
分组
方法是不需要的
SELECT *
FROM   (SELECT *,
               Row_Number()OVER(partition BY Rua, CP Order by id) AS RN
        FROM   Codigo C1) A
WHERE  RN = 1 
SELECT t.*
FROM
  (SELECT t.*, COUNT(1) OVER (partition BY Rua, CP) AS cnt FROM Codigo t
  ) t
WHERE cnt = 1;
SELECT *
FROM Codigo t1
WHERE EXISTS
  (SELECT 1
  FROM Codigo t2
  WHERE t1.Rua    = t2.Rua
  AND t1.CP       = t2.CP
  GROUP BY Rua, CP 
  HAVING COUNT(*) = 1
  );
SELECT C1.*
FROM Codigo C1
INNER JOIN
  (SELECT Rua, CP FROM Codigo C2 GROUP BY Rua, CP HAVING COUNT(*) = 1
  ) C2
ON C1.Rua = C2.Rua
AND C1.CP = C2.CP;