繁体   English   中英

MySQL有子句和Count()

[英]MySQL Having Clause and Count()

我有下表,我正在尝试检索每一个:名称,描述,股票,地址,邮政编码和城市

item1的库存> 10且item2的库存> 10,item3的库存> 5

所以我不希望只包含item1和item2的行,比如ID = 2的行

ID = 1的行也不适合,因为item1的库存<10

这意味着只有ID 3和ID 4的行匹配。 但我不想看到6排,我只需要两排! 包含名称,descr,股票,地址,邮政编码,城市

| ID | NAME | DESCR | STOCK | ADDRESS | POSTALCODE | CITY |
|  1  |  foo  |  item1 |  5 |  addr1 |  po1 | city1 |
| 1  | foo  | item2 | 10 | addr1 | po1 | city1 |
| 1  | foo  | item3 | 5 | addr1 | po1 | city1 |
| 2  | bar  | item1 | 40 | addr2 | po1 | city1 |
| 2  | bar  | item2 | 30 | addr2 | po1 | city1 |
| 3  | smth  | item1 | 25 | addr3 | po3 | city1 |
| 3  | smth  | item2 | 20 | addr3 | po3 | city1 |
| 3  | smth  | item3 | 10 | addr3 | po3 | city1 |
| 4  | els  | item1 | 45 | addr4 | po4 | city1 |
| 4  | els  | item2 | 30 | addr4 | po4 | city1 |
| 4  | els  | item3 | 10 | addr4 | po4 | city1 |

我想我需要这样的东西:

SELECT name, descr, stock , address, postalcode, city
FROM table1
WHERE (descr like 'item1' AND stock >10) 
OR (descr like 'item2' AND stock >10) OR (descr like 'item3' AND stock >5)
GROUP BY name, descr, stock , address, postalcode, city
HAVING COUNT(distinct(somethingIdidNotFigureOutYet)) > 2

我试图计算id,名称甚至描述,但这是不对的。 请有人帮我解决这个问题。 谢谢! (抱歉丑陋的表格格式)

我通常处理这样的问题的方法是将它们分成更小的组,然后根据需要组合查询。 让我们考虑一些事情:

  • 第1项第2项的库存必须大于10,第3项的库存必须大于5。

我们可以提取满足这些要求的行,如下所示:

SELECT id
FROM myTable
GROUP BY id
HAVING 
  SUM(CASE WHEN descr = 'item1' THEN stock else 0 END) > 10 AND 
  SUM(CASE WHEN descr = 'item2' THEN stock else 0 END) > 10 AND 
  SUM(CASE WHEN descr = 'item3' THEN stock else 0 END) > 5;

这将返回ID 3和4.巧​​合的是,这也将满足我们必须至少有一个item1,item2和item3的条件,因为我们在having子句中使用了'AND',这是导致它排除的原因身份2。

这是一个SQL小提琴示例。

在这种情况下,给定WHERE过滤器,您可以将结果集组限制为具有HAVING COUNT(DISTINCT descr) = 3 (或者如果descr在每个组中必然是唯一的,只需HAVING COUNT(*) = 3 )。

然而,更通用的解决方案可能是明确验证每个组是否满足每个标准:

HAVING SUM(descr = 'item1' AND stock > 10)
   AND SUM(descr = 'item2' AND stock > 10)
   AND SUM(descr = 'item3' AND stock >  5)

这是有效的,因为每个SUM()的布尔表达式如果为true则计算为1 ,如果为false则计算为0 ; 因此,对每个组取SUM()导致0如果所有记录都为false,如果为任,则返回非零(并且当在AND operations / HAVING子句的布尔上下文中使用时,产生所需的结果)。

虽然结果集不会受到影响,但出于性能原因,我仍会保留WHERE子句。

您需要从selectgroup by删除descr并将其添加到Having子句以过滤组

试试这个。

SELECT ID,
       NAME, 
       stock, 
       address, 
       postalcode, 
       city 
FROM   table1 
WHERE  ( descr IN ( 'item1', 'item2' ) 
         AND stock > 10 ) 
        OR ( descr = 'item3' 
             AND stock > 5 ) 
GROUP  BY ID,
          NAME, 
          stock, 
          address, 
          postalcode, 
          city 
HAVING Count(DISTINCT descr) = 3

注意:使用没有通配符的 LIKE运算符没有意义,所以我将其更改为=运算符

如果您需要名称和地址信息,那么您可以使用HAVING子句,但您还必须修复GROUP BY子句。 这是一个例子:

SELECT name, address, postalcode, city
FROM table1
GROUP BY name, address, postalcode, city
HAVING SUM(CASE WHEN descr like 'item1' THEN stock END) > 10 AND
       SUM(CASE WHEN descr like 'item2' THEN stock END) > 10 AND
       SUM(CASE WHEN descr like 'item3' THEN stock END) > 5; 

注意:我刚刚将所有条件移动到HAVING子句,因此过滤逻辑位于一个位置。 如果愿意,可以在WHERE子句中重复它。

然后,如果您需要描述和库存量,则一个方法是列表:

SELECT name, address, postalcode, city,
       GROUP_CONCAT(descr, ':', stock SEPARATOR '; ') as items
FROM table1
GROUP BY name, address, postalcode, city
HAVING SUM(CASE WHEN descr like 'item1' THEN stock END) > 10 AND
       SUM(CASE WHEN descr like 'item2' THEN stock END) > 10 AND
       SUM(CASE WHEN descr like 'item3' THEN stock END) > 5; 

如果你想要原始行,那么我会建议INEXISTS

select t.*
from table1 t
where exists (select 1
              from table1 t1
              where t1.id = t.id and t1.descr = 'item1' and t1.stock > 10
             ) and
      exists (select 1
              from table1 t1
              where t1.id = t.id and t1.descr = 'item2' and t1.stock > 10
             ) and
      exists (select 1
              from table1 t1
              where t1.id = t.id and t1.descr = 'item3' and t1.stock > 5
             ) and
      t.descr in ('item1', 'item2', 'item3');

注意:此版本假定对于给定的id不会重复项目。 第一个版本没有做出这个假设。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM