假设我有一个这样的表:
+----+----------+
|name|testValue |
+----+----------+
|A |3 |
+----+----------+
|A |4 |
+----+----------+
|A |7 |
+----+----------+
|B |0 |
+----+----------+
|B |3 |
+----+----------+
|C |5 |
+----+----------+
|C |5 |
+----+----------+
|C |6 |
+----+----------+
现在我首先要按名称对列进行分组,然后才能检索任何行满足特定条件的组。对于每个组,我想检索所有" testValues",我目前正在使用GROUP_CONCAT。
例如,如果我想要检索任何" testValues"的所有组。在4到8之间:
SELECT
name,
testValue,
GROUP_CONCAT(testValue SEPARATOR '#') AS testValues
FROM myTable
GROUP BY name
HAVING testValue > 4 AND testValue < 8
但这只会检查&#34; testValue&#34;组匹配中的第一行。我在这个例子中的预期输出是:
+----+---------+----------+
|name|testValue|testValues|
+----+---------+----------+
|A |3 |3#4#7 |
+----+---------+----------+
|C |5 |5#5#6 |
+----+---------+----------+
虽然我的示例查询的实际输出是:
+----+---------+----------+
|name|testValue|testValues|
+----+---------+----------+
|C |5 |5#5#6 |
+----+---------+----------+
我的问题:
1.我怎样才能检查是否有任何行匹配,而不仅仅是第一行?我甚至应该使用HAVING
吗?
顺便说一下,我已经尝试过google了,但发现它很难。
答案 0 :(得分:5)
您可以使用:
SELECT name, MIN(testValue) AS testValue,
GROUP_CONCAT(testValue SEPARATOR '#') AS testValues
FROM mytable
GROUP BY name
HAVING COUNT(CASE WHEN testValue BETWEEN 4 AND 8 THEN 1 END) > 0
HAVING
子句使用条件聚合来计算[4-8]范围内testValue
值的数量。这将单独应用于每个name
组。
查询只返回满足HAVING
谓词的组。因此,只返回至少一个行[4-8]范围内testValue
的组。
注意:不清楚要将哪个值作为testValue
返回。在OP中提供的样本结果集中,选择最小值。如果您希望实际值在[4-8]范围内,则可以使用:
GROUP_CONCAT(CASE
WHEN testValue BETWEEN 4 AND 8
THEN testValue
END SEPARATOR '#') AS testValue
在查询的SELECT
子句中。
答案 1 :(得分:1)
您正在使用部分分组,因此&#34;仅匹配组中的第一行&#34;问题。
您可以使用内部查询来查找条件匹配的所有名称。然后在外部查询中查找这些名称。使用适当的索引,此方法可以胜过IN
和HAVING
解决方案。
SELECT mytable.name, GROUP_CONCAT(testValue SEPARATOR '#') AS testValues
FROM mytable
INNER JOIN (
SELECT DISTINCT name
FROM mytable
WHERE testValue BETWEEN 4 AND 8
) AS subquery ON mytable.name = subquery.name
GROUP BY mytable.name