2009-08-06 12 views
2

Ich muss das beliebteste Vorkommen eines Artikels nach Datum gruppiert finden und die Gesamtzahl aller Artikel zusammen mit dem Namen dieses Artikels anzeigen. Ist so etwas in einer einzigen Abfrage möglich?mySQL query - zeige die beliebtesten Artikel

Hinweis: Wenn sie alle gleich vorkommen (siehe letzte 3 Zeilen in der Einfügung) als ich kann nur zufällig oder das erste oder letzte Vorkommen zeigen (was am einfachsten ist).

Wenn dies nicht in der SQL getan werden kann dann durch das Ergebnis durchlaufen und sortieren Sie die Daten über PHP, die wie es scheint ziemlich chaotisch sein wird.

Bearbeiten: Sorry, ich hatte die falsche Summe für '2009'08-04'. Es sollte 4.

Ein Beispiel für das, was ich brauche:

 
+------------+---------------------+-------+ 
| 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 | 
+------------+---------------------+-------+ 

Hier ist ein Beispiel-Tabelle:

 
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

Dies kann nicht wirklich richtig beantwortet werden, ohne zu wissen, welches Datum für jeden Artikel gewählt werden sollte, oder ob das wirklich zählt. –

+0

Huh? Er möchte die beliebtesten für jedes Datum. So interpretiere ich: "Ich muss das beliebteste Vorkommen eines nach Datum gruppierten Artikels finden" – hobodave

+0

Ich muss nach dem Datumsfeld gruppieren. In diesem Fall wäre jede Zeile eine "Zusammenfassung" für dieses Datum. – kenitech

Antwort

4

Mein erster Vorschlag war falsche:

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; 

Dies setzt irrtümlicherweise voraus, dass die externe Aggregation (nach Datum) die Option auswählen wird erste Reihe der inneren abgeleiteten Tabelle, die von cnt angeordnet wurde. Dieses Verhalten ist in der Tat nicht definiert und nicht garantiert konsistent. Hier

ist die richtige Lösung:

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; 

Hinweis:

Ich habe die (SELECT COUNT(*)) AS total weil die Frage dies in einer Abfrage gefragt. Dies wird jedoch nicht skaliert, da es sich um eine korrelierte Unterabfrage handelt. Das bedeutet, dass für jeden Zeitpunkt die SELECT COUNT (*) - Unterabfrage ausgeführt wird. Bitte Benchmark und sehen, ob es für Ihre Bedürfnisse geeignet ist. Wenn nicht, dann empfehle ich, die täglichen Summen in einer separaten Abfrage zu erhalten. Sie würden diese Ergebnisse in Ihrer Anwendung zusammenführen.

+0

+1: einfach, gut aussehend ... Und Sie verstanden die Frage ^^ –

+0

Dies wird die Zählung des Artikels, aber nicht die Gesamtzahl der Artikel für dieses Datum geben. – kenitech

+0

Danke hobbodave. Ich habe versucht, mit den ausgegebenen Daten so klar wie möglich zu sein. Ein Kollege von mir hat gerade darauf hingewiesen, dass ich einen weiteren Subselect brauche, um die Summe für das Datum zu zählen. Ich werde dies posten und mir selbst antworten. Ich bin ein N00b auf Overflow, also bitte verzeih mir. – kenitech

0

Dank für seine erste Reaktion auf 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

Das ist so nah wie ich bekommen konnte ....

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 

Das einzige, was dies für Ihre PHP nur zu tun verlässt, ist Anzeige des ersten gefundenen Ergebnisses für ein bestimmtes Datum Ich konnte keinen guten Weg finden, einen Gegenstand willkürlich auszuwählen, wenn es eine Krawatte war. Hoffe das hilft.

+0

Vorbehalt: Ich habe dies in SQL Server getan, weil ich keine mySQL-Instanz zur Hand hatte. Ich bin mir ziemlich sicher, dass die Unterabfrage-Syntax, die ich verwendet habe, funktioniert. – JamieGaines

+0

Dies wird nicht nach Datum gruppiert. Es ist auch unnötig komplex mit 4 abgeleiteten Tabellen. – hobodave