2009-08-06 8 views
2

アイテムで最も人気のあるアイテムを日付でグループ化し、このアイテムの名前とともにすべてのアイテムの合計を表示する必要があります。このようなことは1回のクエリで可能ですか?mySQLクエリ - 最も人気のあるアイテムを表示

注:ランダムに、または最初または最後のオカレンス(どちらか一番簡単なもの)を表示するだけで、それらがすべて同じ出現(挿入の最後の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

これは、各アイテムにどの日付を選択するか、またはこれが本当に重要であるかどうかを知らなければ、実際には正しく答えられません。 –

+0

ハァッ?彼は各日付の中で最も人気のあるものを望んでいます。それは私が解釈する方法です:「最も人気のある出品を日付でグループ化する必要があります」 – hobodave

+0

日付フィールドでグループ化する必要があります。その場合、各行はその日付の「要約」になります。 – kenitech

答えて

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によって順序付けられた内で導出されたテーブルの最初の行。この動作は実際には定義されておらず、一貫性が保証されていません。質問は1つのクエリで、このために尋ねたので、私は(SELECT COUNT(*)) AS totalを追加

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; 

注:ここでは

が適切なソリューションです。ただし、これは相関サブクエリであるため、スケールされません。つまり、すべてのt1.dateに対してSELECT COUNT(*)サブクエリが実行されます。ベンチマークを行い、あなたのニーズに適しているかどうかを確認してください。そうでない場合は、別のクエリで日次合計を取得することをお勧めします。これらの結果をアプリケーションにマージします。彼の初期の応答をhohodaveする

+0

+1:シンプルで素敵な探し方...そして、あなたは質問を理解しました^^ –

+0

これは、その日付の合計アイテムではなく、アイテムのカウントを示します。 – kenitech

+0

ありがとうhobbodave。私は、出力されたデータを可能な限り明確にしようとしました。 私の同僚は、日付の合計を数えるために別の副選択が必要だと指摘しました。私はこれを投稿し、自分自身に答えます。私はオーバーフローのn00bですので、私を許してください。 – kenitech

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; 
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用の葉だけの事はあります指定された日付で最初に見つかった結果を表示します。私は、それがネクタイだったときに1つのアイテムを任意に選ぶ良い方法を見つけられませんでした。お役に立てれば。

+0

警告:私はSQL Serverでこれを行いました。私は手軽にmySQLインスタンスを持っていませんでした。私が使用しているサブクエリの構文はうまくいくはずです。 – JamieGaines

+0

これは日付でグループ化していません。 4つの派生テーブルでも不必要に複雑です。 – hobodave

関連する問題