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

时间:2017-01-14 12:10:45

标签: sql-server group-by unique distinct

我需要SELECT *在以下数据库中使用不同'Rua'的不同'CP'进行SELECT:

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

但我想要所有的专栏。 SELECT *返回“列'Codigo.id'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。”

所以我得到了这个答案:How do I (or can I) SELECT DISTINCT on multiple columns?

我没有找到接受的答案,因为我需要快速查询(这将用于AJAX搜索建议)。我使用了另一个高度赞成的答案。所以,我创建了以下查询:

SELECT * From Codigo
WHERE  (Rua,CP) IN (
   SELECT Rua, CP
   FROM   Codigo
   GROUP  BY Rua, CP
   HAVING COUNT(*) = 1 
);

返回在预期条件,','错误附近的上下文中指定的非布尔类型的表达式。为什么Rua之后的WHERE是布尔值?在答案中,他们使用的saleprice似乎不是布尔值。

所以我的问题是如何选择所有包括具有相同RuaCP的行,但这些只有一次({ {1}})?

2 个答案:

答案 0 :(得分:2)

使用窗口函数(单表读取):

SELECT t.*
FROM
  (SELECT t.*, COUNT(1) OVER (partition BY Rua, CP) AS cnt FROM Codigo t
  ) t
WHERE cnt = 1;

使用EXISTS(读取表格两次):

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; 

答案 1 :(得分:1)

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

使用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的组,以便每个都找到一个Rua行不同的CP

SELECT *
FROM   (SELECT *,
               Count(1)OVER(partition BY Rua, CP) AS cnt
        FROM   Codigo C1) A
WHERE  cnt = 1 

这将是我的首选方法,因为它比使用EXISTS效率更高效,优化程序只需扫描/搜索一次表

如果您不想要重复记录,请使用ROW_NUMBER()

SELECT *
FROM   (SELECT *,
               Row_Number()OVER(partition BY Rua, CP Order by id) AS RN
        FROM   Codigo C1) A
WHERE  RN = 1 

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