2009-08-06 25 views
2

我需要查找按日期分組的項目最常見的情況,並顯示所有項目的總數以及此項目的名稱。在單個查詢中可以這樣做嗎?請注意:如果它們全部相同(請參閱Insert中的最後3行),那麼我可以隨機顯示或第一次或最後一次出現(以最簡單的形式爲準)。mySQL查詢 - 顯示最受歡迎的項目

如果這不能在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

如果不知道每個項目應選擇哪個日期,或者如果這確實很重要,則無法真正回答這個問題。 – 2009-08-06 20:05:01

+0

咦?他希望每個日期最受歡迎。這就是我解釋的方式:「我需要找到按日期分組的項目中最常見的事件」 – hobodave 2009-08-06 20:11:26

+0

我需要按日期字段進行分組,在這種情況下每行都是該日期的「摘要」。 – kenitech 2009-08-06 20:12:03

回答

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(*)子查詢都會運行。請進行基準測試,看它是否適合您的需求。如果不是,那麼我建議在單獨的查詢中獲取每日總計。您會將這些結果合併到您的應用程序中。

+0

+1:簡單,好看...而且你理解了這個問題^^ – 2009-08-06 20:24:56

+0

這將給出該項目的計數,但不是該日期的總項目。 – kenitech 2009-08-06 20:30:17

+0

謝謝hobbodave。我試圖儘可能清楚輸出的數據。 我的一位同事剛剛指出,我需要另一個子選票來計算日期的總數。我會發布這個並回答我自己。我是Overflow的n00b,所以請原諒我。 – kenitech 2009-08-06 20:49:07

0

感謝hohodave他最初的反應:

 
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; 
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做的唯一的事情就是唯一的顯示它在給定日期找到的第一個結果。我無法想出一個很好的方法來任意選擇一個項目,當它是一個領帶。希望這可以幫助。

+0

警告:我在SQL Server中這樣做,因爲我沒有方便的mySQL實例。我很確定我使用的子查詢語法可以工作。 – JamieGaines 2009-08-06 21:03:51

+0

這不按日期分組。這對於4個派生表也是不必要的複雜。 – hobodave 2009-08-06 21:23:50