【问题标题】:SELECT all columns from distinct two columns从不同的两列中选择所有列
【发布时间】:2017-01-14 12:10:45
【问题描述】:

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

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 
);

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

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

【问题讨论】:

    标签: sql-server group-by unique distinct


    【解决方案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 的组,以在每个不同的CP 中找到一个Rua 行。

    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 列对重复记录进行了排序,并从重复记录中挑选了第一条记录。

    【讨论】:

    • 两者都有效。第一个建议需要 33 秒,秒需要 3 :) 为什么会有这样的差异?
    • @Dillinger - 因为优化器必须在第二种方法中只扫描/查找表一次
    • 我想我没有正确提出问题。我希望也包含具有相同RuaCP 的行,但只包含一次。有了这个,我只得到不重复RuaCP 的结果。如果我编辑并修正我的问题,你会修正你的答案吗?
    • @Dillinger - 是的。
    【解决方案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; 
    

    【讨论】:

    • GROUP BY in Exists 方法不需要
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-30
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多