MySQL:带有隐式 GROUP BY 的 COUNT
MySQL: COUNT with implicit GROUP BY
一段时间以来,我一直在猜测如何解决我的问题,但似乎找不到解决方案,所以我来找你,专家们。
我有什么
A MySQL table 具有以下结构和值(作为示例):
+----+---------+----------------+-----------------+--------------+
| id | item_id | attribute_name | attribute_value | deleted_date |
+----+---------+----------------+-----------------+--------------+
| 1 | 2 | action | call | NULL |
| 2 | 2 | person | Joseph | NULL |
| 3 | 2 | action | fault | NULL |
| 4 | 2 | otherattr | otherval | NULL |
| 5 | 5 | action | call | NULL |
| 6 | 5 | person | Mike | NULL |
| 7 | 5 | action | sprint | NULL |
| 8 | 8 | action | call | NULL |
| 9 | 8 | person | Joseph | NULL |
| 10 | 8 | action | block | NULL |
| 11 | 8 | action | call | NULL |
+----+---------+----------------+-----------------+--------------+
我需要什么
我想向 return 查询有多少项 (item_id) 至少有一个 attribute_name 'action' 和 attribute_value作为 'call',按 'person' 分组,但只计算其中一个。
因此,如果 - 就像在示例中一样,在 id 8 和 11 - 有一个 item_id 和两个 "action" = "call",只有 COUNT
其中之一他们。
查询应该return像这样:
+--------+--------------+
| person | action_calls |
+--------+--------------+
| Joseph | 2 |
| Mike | 1 |
+--------+--------------+
问题
问题是我不知道如何以简单的方式做到这一点,这不会带来巨大的性能提升,因为这个查询将是return 沿着很多行搜索和搜索 - 在某些情况下 return 也搜索了很多行。
我唯一想到的是嵌套和嵌套查询,我想避免这种情况。
如果我创建一个 COUNT(DISTINCT)
,它只会 return 在 'Joseph' 中是 '1',因为值总是 'call'、 和 如果我 GROUP BY b.item_id
,它 return 将我和 Joseph 排成两行(而且,在这种情况下,它也计算两个 'call' 属性,所以它不会是解决方案都没有)。
我试过的
我试过的查询如下:
SELECT a.attribute_value AS person, COUNT(b.attribute_value) AS action_calls
FROM `er_item_attributes` a, `er_item_attributes` b
WHERE a.attribute_name = 'person'
AND b.item_id IN (SELECT DISTINCT item_id FROM er_item_parents WHERE parent_id IN (1234,4567))
AND b.item_id = a.item_id
AND b.attribute_name = 'action'
AND b.attribute_value = 'call'
AND b.deleted_date IS NULL
GROUP BY a.attribute_value, b.attribute_name
附加信息
如您所见,item_id 也会从内部 WHERE 子句中选择,因为有效的子句在另一个 table 中(就像父子 table). parent_id 数字仅供参考,与此无关。
总结
我怎样才能使 MySQL 中的 COUNT
表现得像 COUNT GROUP BY
,而不嵌套 SELECT
会降低性能?
如果需要任何进一步的信息,请发表评论,我会尽力添加。
此外,欢迎就查询提高性能所需信息的其他方法提出任何建议。
感谢大家的宝贵时间和帮助!
亲切的问候。
试试这个!
SELECT attribute_value AS person, COUNT(*) FROM `stack_1239`
WHERE item_id IN (
SELECT item_id FROM `stack_1239` WHERE attribute_name = 'action' AND attribute_value = 'call'
)
AND attribute_name = 'person'
GROUP BY person;
:)
DROP TABLE IF EXISTS eav_hell;
CREATE TABLE eav_hell
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,entity INT NOT NULL
,attribute VARCHAR(20) NOT NULL
,value VARCHAR(20) NOT NULL
);
INSERT INTO eav_hell
VALUES
( 1 ,2 ,'action','call'),
( 2 ,2 ,'person','Joseph'),
( 3 ,2 ,'action','fault'),
( 4 ,2 ,'otherattr','otherval'),
( 5 ,5 ,'action','call'),
( 6 ,5 ,'person','Mike'),
( 7 ,5 ,'action','sprint'),
( 8 ,8 ,'action','call'),
( 9 ,8 ,'person','Joseph'),
(10 ,8 ,'action','block'),
(11 ,8 ,'action','call');
SELECT e1.entity
, e1.value person
, e2.value action
, COUNT(*)
FROM eav_hell e1
LEFT
JOIN eav_hell e2
ON e2.entity = e1.entity
AND e2.attribute = 'action'
AND e2.value = 'call'
WHERE e1.attribute = 'person'
GROUP
BY entity
, person
, action;
+--------+--------+--------+----------+
| entity | person | action | COUNT(*) |
+--------+--------+--------+----------+
| 2 | Joseph | call | 1 |
| 5 | Mike | call | 1 |
| 8 | Joseph | call | 2 |
+--------+--------+--------+----------+
编辑:
SELECT e1.value person
, e2.value action
, COUNT(DISTINCT e1.entity)
FROM eav_hell e1
LEFT
JOIN eav_hell e2
ON e2.entity = e1.entity
AND e2.attribute = 'action'
AND e2.value = 'call'
WHERE e1.attribute = 'person'
GROUP
BY person
, action;
+--------+--------+---------------------------+
| person | action | COUNT(DISTINCT e1.entity) |
+--------+--------+---------------------------+
| Joseph | call | 2 |
| Mike | call | 1 |
+--------+--------+---------------------------+
一段时间以来,我一直在猜测如何解决我的问题,但似乎找不到解决方案,所以我来找你,专家们。
我有什么
A MySQL table 具有以下结构和值(作为示例):
+----+---------+----------------+-----------------+--------------+
| id | item_id | attribute_name | attribute_value | deleted_date |
+----+---------+----------------+-----------------+--------------+
| 1 | 2 | action | call | NULL |
| 2 | 2 | person | Joseph | NULL |
| 3 | 2 | action | fault | NULL |
| 4 | 2 | otherattr | otherval | NULL |
| 5 | 5 | action | call | NULL |
| 6 | 5 | person | Mike | NULL |
| 7 | 5 | action | sprint | NULL |
| 8 | 8 | action | call | NULL |
| 9 | 8 | person | Joseph | NULL |
| 10 | 8 | action | block | NULL |
| 11 | 8 | action | call | NULL |
+----+---------+----------------+-----------------+--------------+
我需要什么
我想向 return 查询有多少项 (item_id) 至少有一个 attribute_name 'action' 和 attribute_value作为 'call',按 'person' 分组,但只计算其中一个。
因此,如果 - 就像在示例中一样,在 id 8 和 11 - 有一个 item_id 和两个 "action" = "call",只有 COUNT
其中之一他们。
查询应该return像这样:
+--------+--------------+
| person | action_calls |
+--------+--------------+
| Joseph | 2 |
| Mike | 1 |
+--------+--------------+
问题
问题是我不知道如何以简单的方式做到这一点,这不会带来巨大的性能提升,因为这个查询将是return 沿着很多行搜索和搜索 - 在某些情况下 return 也搜索了很多行。
我唯一想到的是嵌套和嵌套查询,我想避免这种情况。
如果我创建一个 COUNT(DISTINCT)
,它只会 return 在 'Joseph' 中是 '1',因为值总是 'call'、 和 如果我 GROUP BY b.item_id
,它 return 将我和 Joseph 排成两行(而且,在这种情况下,它也计算两个 'call' 属性,所以它不会是解决方案都没有)。
我试过的
我试过的查询如下:
SELECT a.attribute_value AS person, COUNT(b.attribute_value) AS action_calls
FROM `er_item_attributes` a, `er_item_attributes` b
WHERE a.attribute_name = 'person'
AND b.item_id IN (SELECT DISTINCT item_id FROM er_item_parents WHERE parent_id IN (1234,4567))
AND b.item_id = a.item_id
AND b.attribute_name = 'action'
AND b.attribute_value = 'call'
AND b.deleted_date IS NULL
GROUP BY a.attribute_value, b.attribute_name
附加信息
如您所见,item_id 也会从内部 WHERE 子句中选择,因为有效的子句在另一个 table 中(就像父子 table). parent_id 数字仅供参考,与此无关。
总结
我怎样才能使 MySQL 中的 COUNT
表现得像 COUNT GROUP BY
,而不嵌套 SELECT
会降低性能?
如果需要任何进一步的信息,请发表评论,我会尽力添加。
此外,欢迎就查询提高性能所需信息的其他方法提出任何建议。
感谢大家的宝贵时间和帮助!
亲切的问候。
试试这个!
SELECT attribute_value AS person, COUNT(*) FROM `stack_1239`
WHERE item_id IN (
SELECT item_id FROM `stack_1239` WHERE attribute_name = 'action' AND attribute_value = 'call'
)
AND attribute_name = 'person'
GROUP BY person;
:)
DROP TABLE IF EXISTS eav_hell;
CREATE TABLE eav_hell
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,entity INT NOT NULL
,attribute VARCHAR(20) NOT NULL
,value VARCHAR(20) NOT NULL
);
INSERT INTO eav_hell
VALUES
( 1 ,2 ,'action','call'),
( 2 ,2 ,'person','Joseph'),
( 3 ,2 ,'action','fault'),
( 4 ,2 ,'otherattr','otherval'),
( 5 ,5 ,'action','call'),
( 6 ,5 ,'person','Mike'),
( 7 ,5 ,'action','sprint'),
( 8 ,8 ,'action','call'),
( 9 ,8 ,'person','Joseph'),
(10 ,8 ,'action','block'),
(11 ,8 ,'action','call');
SELECT e1.entity
, e1.value person
, e2.value action
, COUNT(*)
FROM eav_hell e1
LEFT
JOIN eav_hell e2
ON e2.entity = e1.entity
AND e2.attribute = 'action'
AND e2.value = 'call'
WHERE e1.attribute = 'person'
GROUP
BY entity
, person
, action;
+--------+--------+--------+----------+
| entity | person | action | COUNT(*) |
+--------+--------+--------+----------+
| 2 | Joseph | call | 1 |
| 5 | Mike | call | 1 |
| 8 | Joseph | call | 2 |
+--------+--------+--------+----------+
编辑:
SELECT e1.value person
, e2.value action
, COUNT(DISTINCT e1.entity)
FROM eav_hell e1
LEFT
JOIN eav_hell e2
ON e2.entity = e1.entity
AND e2.attribute = 'action'
AND e2.value = 'call'
WHERE e1.attribute = 'person'
GROUP
BY person
, action;
+--------+--------+---------------------------+
| person | action | COUNT(DISTINCT e1.entity) |
+--------+--------+---------------------------+
| Joseph | call | 2 |
| Mike | call | 1 |
+--------+--------+---------------------------+