我需要查找按日期分组的项目中最常见的事件,并显示所有项目的总数以及此项目的名称。在单个查询中是否可以这样?
注意:如果它们全部相同(参见插入中的最后3行),我可以随机显示或第一次或最后一次出现(以最简单的方式)。
如果在sql中无法做到这一点,则必须运行结果并通过PHP对数据进行排序,这看起来很混乱。
编辑:对不起,'2009 '08-04'的错误总数。它应该是4。
我需要的一个例子:
+------------+---------------------+-------+ | date | item | total | +------------+---------------------+-------+ | 2009-08-02 | Apple | 5 | | 2009-08-03 | Pear | 2 | | 2009-08-04 | Peach | 4 | | 2009-08-05 | Apple | 1 | | 2009-08-06 | Apple | 3 | +------------+---------------------+-------+
这是一个示例表:
CREATE TABLE IF NOT EXISTS `test_popularity` ( `date` datetime NOT NULL, `item` varchar(256) NOT NULL, `item_id` int(11) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `test_popularity` (`date`, `item`, `item_id`) VALUES ('2009-08-02 00:00:00', 'Apple', 1), ('2009-08-02 00:00:00', 'Pear', 3), ('2009-08-02 00:00:00', 'Apple', 1), ('2009-08-02 00:00:00', 'Apple', 1), ('2009-08-02 00:00:00', 'Pear', 0), ('2009-08-03 00:00:00', 'Pear', 3), ('2009-08-03 00:00:00', 'Peach', 2), ('2009-08-04 00:00:00', 'Apple', 1), ('2009-08-04 00:00:00', 'Peach', 2), ('2009-08-04 00:00:00', 'Peach', 2), ('2009-08-04 00:00:00', 'Pear', 3), ('2009-08-05 00:00:00', 'Apple', 1), ('2009-08-06 00:00:00', 'Apple', 1), ('2009-08-06 00:00:00', 'Peach', 2), ('2009-08-06 00:00:00', 'Pear', 3);
答案 0 :(得分:4)
我的初步建议不正确:
SELECT
date, item, SUM(cnt)
FROM (
SELECT
date, item, count(item_id) AS cnt
FROM test_popularity
GROUP BY date, item_id
ORDER BY cnt DESC
) t
GROUP BY date;
这错误地假设外部聚合(按日期)将选择由cnt排序的内部派生表的第一行。事实上,这种行为是未定义的,并且不能保证一致。
这是正确的解决方案:
SELECT
t1.date, t1.item,
(SELECT COUNT(*) FROM test_popularity WHERE date = t1.date) as total
# see note!
FROM test_popularity t1
JOIN (
SELECT date, item, item_id, COUNT(item_id) as count
FROM test_popularity
GROUP BY date, item_id
) AS t2
ON t1.date = t2.date AND t1.item_id = t2.item_id
GROUP BY t1.date;
注意:
我添加了(SELECT COUNT(*)) AS total
,因为在一个查询中提出了这个问题。但是,这不会缩放,因为它是相关的子查询。这意味着对于每个t1.date,SELECT COUNT(*)子查询将运行。请进行基准测试,看看它是否适合您的需求。如果没有,那么我建议在单独的查询中获取每日总计。您可以在应用程序中合并这些结果。
答案 1 :(得分:0)
SELECT date, item, cnt, ( SELECT COUNT( * ) FROM test_popularity WHERE date = t.date ) AS totalCnt FROM ( SELECT date, item, count( item_id ) AS cnt FROM test_popularity GROUP BY date, item_id ORDER BY cnt DESC )t GROUP BY date;
答案 2 :(得分:0)
这是我能得到的尽可能接近......
SELECT DISTINCT p.date, ItemTotalsByDate.Item, DateTotals.Total
FROM test_popularity p
INNER JOIN
(SELECT date, MAX(cnt) DayMax from
(SELECT date, item, COUNT(*) cnt
FROM dbo.test_popularity
GROUP BY date, item) tbl
GROUP BY date) MaxesByDate
ON p. date = MaxesByDate.date
INNER JOIN
(SELECT date, item, COUNT(*) Total FROM dbo.test_popularity
GROUP BY date, item) ItemTotalsByDate
ON MaxesByDate.date = ItemTotalsByDate.date AND MaxesByDate.DayMax = ItemTotalsByDate.Total
INNER JOIN
(SELECT date, COUNT(*) Total FROM dbo.test_popularity
GROUP BY date) DateTotals
ON p.date = DateTotals.date
这给PHP留下的唯一事情就是只显示它为给定日期找到的第一个结果。我无法想出一个好的方法,当它是一个领带时随意选择一个项目。希望这会有所帮助。