MySQL-选择列值仅为0的行,按另一列分组?

时间:2018-09-13 11:51:59

标签: mysql sql database select

示例表:

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,请不要选择foreign_id。预期输出:

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

任何帮助表示赞赏。

5 个答案:

答案 0 :(得分:1)

使用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'

答案 1 :(得分:1)

您可以使用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
                 );

答案 2 :(得分:1)

(我对此进行了编辑以证明其有效并阐明了一些内容):

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

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

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

尝试一下:

var b= new DataTable("B");

DataColumn id= new DataColumn("Id", typeof(int));
billablePriceMapId.AutoIncrement = true;
billable.Columns.Add(id);

DataColumn parentId= new DataColumn("ParentGuid", typeof(Guid));
billable.Columns.Add(parentGuid);

DataColumn[] keys = new DataColumn[1];
keys[0] = id;
billable.PrimaryKey = keys;



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

然后我输入以下代码:
enter image description here

我得到了以下结果:
enter image description here



让我知道您是否有任何疑问!

答案 3 :(得分:1)

正如其他人所说,您应该汇总数据,但是与此同时存在很多潜在的问题。但是在开始之前,您已经声明要在输出中显示原始记录,而不是合并数据,最简单的解决方案是使用2个查询-一个用于标识仅status = 0的foreign_id,另一个用于获取对应的行

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

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

在这种情况下,“状态” <0会被卡住。输出将包括这些行(SUM()可能会发生相同的情况)。有几种解决方法,例如,可以使用SUM(ABS(status))或SUM(IF(status = 0,0,1))。正如Madhur所建议的那样,您还可以GROUP_CONCAT(status)并检查列的输出是否仅为'0'。

但是我怀疑您要告诉我状态不能为负(或为null?),因为它是nominal number。如果是这种情况,则说明您使用了错误的数据类型-您应该使用ENUM。如果真是这样,则您不能将SUM()或MAX()应用于枚举,但仍可以使用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

答案 4 :(得分:0)

使用聚合函数

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