Як отримати найбільш часто зустрічається категорію для кожного тегу в MySQL? В ідеалі, я хотів би імітувати сукупну функцію, яка б обчислила режим колонки.
SELECT
t.tag
, s.category
FROM tags t
LEFT JOIN stuff s
USING (id)
ORDER BY tag;
+------------------+----------+
| tag | category |
+------------------+----------+
| automotive | 8 |
| ba | 8 |
| bamboo | 8 |
| bamboo | 8 |
| bamboo | 8 |
| bamboo | 8 |
| bamboo | 8 |
| bamboo | 10 |
| bamboo | 8 |
| bamboo | 9 |
| bamboo | 8 |
| bamboo | 10 |
| bamboo | 8 |
| bamboo | 9 |
| bamboo | 8 |
| banana tree | 8 |
| banana tree | 8 |
| banana tree | 8 |
| banana tree | 8 |
| bath | 9 |
+-----------------------------+
Відповіді:
3 для відповіді № 1SELECT t1.*
FROM (SELECT tag, category, COUNT(*) AS count
FROM tags INNER JOIN stuff USING (id)
GROUP BY tag, category) t1
LEFT OUTER JOIN
(SELECT tag, category, COUNT(*) AS count
FROM tags INNER JOIN stuff USING (id)
GROUP BY tag, category) t2
ON (t1.tag = t2.tag AND (t1.count < t2.count
OR t1.count = t2.count AND t1.category < t2.category))
WHERE t2.tag IS NULL
ORDER BY t1.count DESC;
Я погоджуюся, що це занадто багато для одного запиту SQL. Будь-яке використання GROUP BY
всередині підзапиту змушує мене здригнутися. Ви можете зробити це дивись простіше за допомогою переглядів:
CREATE VIEW count_per_category AS
SELECT tag, category, COUNT(*) AS count
FROM tags INNER JOIN stuff USING (id)
GROUP BY tag, category;
SELECT t1.*
FROM count_per_category t1
LEFT OUTER JOIN count_per_category t2
ON (t1.tag = t2.tag AND (t1.count < t2.count
OR t1.count = t2.count AND t1.category < t2.category))
WHERE t2.tag IS NULL
ORDER BY t1.count DESC;
Але це в основному робить ту ж саму роботу за лаштунками.
Ви коментуєте, що ви можете легко виконати подібну операцію в коді програми. Так чому б не зробити це? Зробіть більш простий запит, щоб отримати підрахунок для кожної категорії:
SELECT tag, category, COUNT(*) AS count
FROM tags INNER JOIN stuff USING (id)
GROUP BY tag, category;
І сортуйте результат у коді програми.
3 для відповіді № 2
(Редагувати: забули DESC у ORDER BYs)
Легко зробити з LIMIT у підзапиті. Чи існує у MySQL обмеження no-LIMIT-in-subqueries? Нижче наведено приклад використання PostgreSQL.
=> select tag, (select category from stuff z where z.tag = s.tag group by tag, category order by count(*) DESC limit 1) AS category, (select count(*) from stuff z where z.tag = s.tag group by tag, category order by count(*) DESC limit 1) AS num_items from stuff s group by tag;
tag | category | num_items
------------+----------+-----------
ba | 8 | 1
automotive | 8 | 1
bananatree | 8 | 4
bath | 9 | 1
bamboo | 8 | 9
(5 rows)
Третій стовпець необхідний тільки, якщо вам потрібний підрахунок.
2 для відповіді № 3
SELECT tag, category
FROM (
SELECT @tag <> tag AS _new,
@tag := tag AS tag,
category, COUNT(*) AS cnt
FROM (
SELECT @tag := ""
) vars,
stuff
GROUP BY
tag, category
ORDER BY
tag, cnt DESC
) q
WHERE _new
На ваших даних буде повернуто наступне:
"automotive", 8
"ba", 8
"bamboo", 8
"bananatree", 8
"bath", 9
Сценарій тесту:
CREATE TABLE stuff (tag VARCHAR(20) NOT NULL, category INT NOT NULL);
INSERT
INTO stuff
VALUES
("automotive",8),
("ba",8),
("bamboo",8),
("bamboo",8),
("bamboo",8),
("bamboo",8),
("bamboo",8),
("bamboo",10),
("bamboo",8),
("bamboo",9),
("bamboo",8),
("bamboo",10),
("bamboo",8),
("bamboo",9),
("bamboo",8),
("bananatree",8),
("bananatree",8),
("bananatree",8),
("bananatree",8),
("bath",9);
1 для відповіді № 4
Це для більш простих ситуацій:
SELECT action, COUNT(action) AS ActionCount
FROM log
GROUP BY action
ORDER BY ActionCount DESC;