MySQL 有 Clause 和 Count()
MySQL Having Clause and Count()
我有以下 table 我正在尝试检索每一个:
姓名、描述、股票、地址、邮政编码和城市
其中 item1 的库存 > 10 AND item2 的库存 > 10 AND item3 的库存 > 5
所以我不想要只包含 item1 和 item2 的行,比如 ID = 2 的行
ID = 1 的行也放不下,因为 item1 的库存 < 10
这意味着只有 ID 3 和 ID 4 的行匹配。但我不想看到 6 行,我只需要两行!包含名称、描述、股票、地址、邮政编码、城市
| 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,名字,甚至是描述,但都不对。有人可以帮我解决这个问题吗?谢谢! (对于难看的 table 格式感到抱歉)
鉴于本例中的 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()
中的布尔表达式如果为真则计算为 1
,如果为假则计算为 0
;因此,对每个组取 SUM()
会导致 0
如果所有记录都为假,或者 non-zero 如果对任何记录为真(并且在 AND
操作的布尔上下文中使用时 / HAVING
子句,产生所需的结果)。
虽然结果集不受影响,但出于性能原因,我还是会保留 WHERE
子句。
您需要从 select
和 group 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;
如果你想要原始行,那么我建议 IN
或 EXISTS
:
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
,项目不会重复。第一个版本没有做这个假设。
我通常处理此类问题的方法是将它们分解成更小的组,然后根据需要组合查询。让我们考虑一些事情:
- 商品 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;
这将 return ids 3 和 4。巧合的是,这也将满足我们必须至少有一个 item1、item2 和 item3 的条件,因为我们在中使用了 'AND'我们的 having 子句,这就是导致它排除 id 2 的原因。
这是一个 SQL Fiddle 示例。
我有以下 table 我正在尝试检索每一个: 姓名、描述、股票、地址、邮政编码和城市
其中 item1 的库存 > 10 AND item2 的库存 > 10 AND item3 的库存 > 5
所以我不想要只包含 item1 和 item2 的行,比如 ID = 2 的行
ID = 1 的行也放不下,因为 item1 的库存 < 10
这意味着只有 ID 3 和 ID 4 的行匹配。但我不想看到 6 行,我只需要两行!包含名称、描述、股票、地址、邮政编码、城市
| 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,名字,甚至是描述,但都不对。有人可以帮我解决这个问题吗?谢谢! (对于难看的 table 格式感到抱歉)
鉴于本例中的 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()
中的布尔表达式如果为真则计算为 1
,如果为假则计算为 0
;因此,对每个组取 SUM()
会导致 0
如果所有记录都为假,或者 non-zero 如果对任何记录为真(并且在 AND
操作的布尔上下文中使用时 / HAVING
子句,产生所需的结果)。
虽然结果集不受影响,但出于性能原因,我还是会保留 WHERE
子句。
您需要从 select
和 group 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;
如果你想要原始行,那么我建议 IN
或 EXISTS
:
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
,项目不会重复。第一个版本没有做这个假设。
我通常处理此类问题的方法是将它们分解成更小的组,然后根据需要组合查询。让我们考虑一些事情:
- 商品 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;
这将 return ids 3 和 4。巧合的是,这也将满足我们必须至少有一个 item1、item2 和 item3 的条件,因为我们在中使用了 'AND'我们的 having 子句,这就是导致它排除 id 2 的原因。
这是一个 SQL Fiddle 示例。