2012-03-27 11 views
1

Ich habe 2 Tabellen.Komplexe PHP-Abfrage

books (id, sku, name, description, date_added) 

und

books_views (id, sku, date_viewed) 

Ich versuche, eine optimierte Abfrage zu schreiben folgendes zu tun.

  1. Um die am häufigsten betrachteten Bücher für die letzte Woche zu finden
  2. zu finden, die am häufigsten betrachteten Bücher für den letzten Monat

Die books_views Tabelle mehr als 4 Millionen Einträge hat. Was wäre der beste Weg, um die Daten nach Ansichten für Woche und Monat zu sortieren?

+0

Wo ist die Anzahl der gespeicherten Ansichten? Was hast du probiert? – jordanm

+0

@jordanm: Vermutlich wird für jede Ansicht eine neue Zeile zu 'books_views' hinzugefügt. –

+0

Eine neue_Zeile wird zu book_views hinzugefügt. Ich habe jeden Abend versucht, einen Tisch builds_weekly_views (sku, count) zu erstellen und dann zu benutzen, aber denke nicht, dass das effizient ist. – daydreamer

Antwort

2

Die Abfrage ist:

SELECT sku, count(*) AS times_viewed 
FROM book_views bv 
WHERE date_viewed > DATE_SUB(NOW(), INTERVAL 7 DAY) 
GROUP BY sku 
ORDER BY times_viewed DESC 

Um die Ansichten für den Monat zu erhalten, bis 30 Tage, um das Intervall zu ändern.

Um es schnell zu machen, müssen Sie sicherstellen, dass die Tabelle ordnungsgemäß indiziert ist. Sie werden sicher einen Index auf date_viewed wollen. Wenn Sie auch die Buchnamen möchten, sollten Sie die Spalten sku in beiden Tabellen indizieren. So würden Sie auch die Buchnamen erhalten.

SELECT bv.sku, name, count(*) AS times_viewed 
FROM book_views bv JOIN books b ON bv.sku = b.sku 
WHERE date_viewed > DATE_SUB(NOW(), INTERVAL 7 DAY) 
GROUP BY bv.sku 
ORDER BY times_viewed DESC 
+0

Wie können Sie einen Index für "times_viewed" haben? Es ist ein Alias. –

+1

Gemeint date_viewed natürlich. – Rafe

+0

Funktioniert gut, aber dauert etwa 5,3 Sekunden. Ist das in Ordnung? – daydreamer

0

Sofern Ihre books_views Tabelle hat andere Felder, die Sie hier nicht zeigen werden, sollten Sie Ihre Ansichten Tabelle ändern - books_views (sku, date_viewed, views) mit der PK auf sku und date_viewed.

ändern Sie dann Ihren Einsatz ein Einsatz auf dup Schlüssel zu sein -

INSERT INTO books_views VALUES ('sku', CURRENT_DATE, 1) 
    ON DUPLICATE KEY UPDATE views = views + 1; 

Wenn Sie die beste Leistung wünschen, mehr Updates als Einsätze vorausgesetzt, Sie tun könnten -

UPDATE books_views 
SET views = views + 1 
WHERE sku = 'sku' 
AND date_viewed = CURRENT_DATE; 

dann prüfen, für die Anzahl der betroffenen Zeilen und dann einfügen, wenn keine Zeilen betroffen sind -

INSERT INTO books_views VALUES ('sku', CURRENT_DATE, 1);