【问题标题】:MySQL - Select rows where column value is only 0, group by another column?MySQL - 选择列值仅为0的行,按另一列分组?
【发布时间】:2019-02-18 03:43:01
【问题描述】:

示例表:

ID, foreign_id, status

ID独特的foreign_id 不是。示例行:

1, 1111, 0  
2, 2222, 0  
3, 3333, 1
4, 1111, 1
5, 4444, 0

我要选择的是唯一的foreign_id,只有状态为 0。如果它的状态为 0,但具有相同外部 ID 的另一行的状态为 1,请不要选择该 @ 987654326@。预期输出:

1, 2222, 0
5, 4444, 0

我可以选择status = 0 的位置并按foreign_id 分组,但这只会选择状态为0 的行,即使可能有另一行具有相同的foreign_id 和状态为1。

SELECT ID, foreign_id 
FROM table 
WHERE status = 0 
GROUP BY foreign_id

任何帮助表示赞赏。

【问题讨论】:

    标签: mysql sql database select


    【解决方案1】:

    (我对此进行了编辑以证明它有效并澄清了一些事情):

    您可能感兴趣的是 HAVING 语句。

    您可以在 GROUP BY 之后使用 HAVING 语句。这是一个很好的解释: https://www.dofactory.com/sql/having

    简而言之,HAVING 语句的作用是让您过滤作为 GROUP BY 表达式的结果返回的数据。

    试试这个:

    SELECT 
         foreign_id, MAX(status) AS status
    FROM
         myTable
    GROUP BY 
         foreign_id
    HAVING 
         MAX(status) = 0
    



    这是一个工作示例(在基本的 MS Access 文件中测试):

    然后我输入了以下代码:

    我得到了这些结果:



    如果您有任何问题,请告诉我!

    【讨论】:

      【解决方案2】:

      使用GROUP_CONCATDISTINCT 子句,我们针对foreign_id 对所有唯一状态分组。现在在HAVING 子句中,我们只需要过滤掉那些foreign_id,其中唯一状态是'0'

      尝试以下方法:

      SELECT ID, foreign_id, status, GROUP_CONCAT(DISTINCT status) as statuses 
      FROM table 
      GROUP BY foreign_id 
      HAVING statuses = '0'
      

      【讨论】:

      • 使用 GROUP_CONCAT 的好主意 - 但如果没有 GROUP BY foreign_id,查询将不会返回相关数据,然后您会丢失 id - 因此您的查询不会过滤正确的 foreign_id 记录并且不会t 输出所需的属性
      • @symcbean 我的查询中有一个 GROUP BY 子句。请进一步澄清。
      • 尝试运行它 - 看看 ID 会发生什么 - 如果您的 DBMS 配置为使用严格的语法,您将收到错误消息,或者它会报告它看到的“id”的最后一个值 - OP想要所有的 ID。
      【解决方案3】:

      您可以使用group byhaving

      select foreign_id, max(status) as status
      from t
      group by foreign_id
      having max(status) = 0;
      

      基本上,你需要在group by之后进行测试

      如果您想要完整的行,请使用not exists:

      select t.*
      from t
      where not exists (select 1
                        from t t2
                        where t2.foreign_id = t.foreign_id and t2.status <> 0
                       );
      

      【讨论】:

        【解决方案4】:

        正如其他人所说,您应该汇总数据,但这样做存在很多潜在问题。但在我们开始之前,您已经声明您想要输出中的原始记录 - 而不是合并数据 - 最简单的解决方案是使用 2 个查询 - 一个用于识别仅 status=0 的 foreign_ids,一个用于获取相应的行

        SELECT r.*
        FROM examples r
        JOIN ( SELECT s.foreign_id, MAX(s.status)
          FROM examples s
          GROUP BY s.foreign_id
          HAVING MAX(s.status)=0
        ) t
        ON r.foreign_id=t.foreign_id
        

        或者,您可以在 status!=0 处获取 foreign_ids 并在第二个查询中排除这些 - 这可能更有效,具体取决于您的数据分布。

        在“status”

        但我怀疑你要告诉我状态不能为负(或 null?),因为它是 nominal number。如果是这种情况,那么您使用了错误的数据类型 - 您应该使用 ENUM。如果是这种情况,那么您不能将 SUM() 或 MAX() 应用于 ENUM,但您仍然可以使用 SUM(IF(status=?,0,1)) 或 GROUP_CONCAT() 方法。

        因此....

        SELECT r.*
        FROM examples r
        JOIN ( SELECT s.foreign_id, SUM(IF(status=0,0,1))
          FROM examples s
          GROUP BY s.foreign_id
          HAVING SUM(IF(status=0,0,1))=0
        ) t
        ON r.foreign_id=t.foreign_id
        

        【讨论】:

          【解决方案5】:

          使用聚合函数

          select * from t where foreign_id in (
               select foreign_id
                  from t
                  group by foreign_id
                  having min(status) = 0
                 ) and status!=1
          

          【讨论】:

            猜你喜欢
            • 2017-01-22
            • 2020-10-01
            • 2013-06-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-11
            • 2020-11-14
            相关资源
            最近更新 更多