2013-01-09 6 views
6

Ich habe eine Datenbank mit einer Items Tabelle, die etwa wie folgt aussieht:MYSQL Select One Zufalls Datensatz aus jeder Kategorie

id 
name 
category (int) 

Es gibt mehrere hunderttausend Datensätze. Jeder item kann in einer von 7 verschiedenen categories, die zu einer categories Tabelle entsprechen:

id 
category 

ich eine Abfrage möchten, die 1 Zufallsgenerator wählt aus jeder Kategorie. Was ist der beste Weg, um das zu erreichen? Ich weiß Order By rand() und LIMIT 1 für ähnliche zufällige Abfragen zu verwenden, aber ich habe so etwas noch nie gemacht.

Antwort

5

Diese Abfrage liefert alle Artikel Kategorien in zufälliger Reihenfolge verbunden :

SELECT 
c.id AS cid, c.category, i.id AS iid, i.name 
FROM categories c 
INNER JOIN items i ON c.id = i.category 
ORDER BY RAND() 

Um jede Kategorie ein, wickeln Sie die Abfrage in einem TeilGROUP BY einschränken:

SELECT * FROM (
    SELECT 
    c.id AS cid, c.category, i.id AS iid, i.name 
    FROM categories c 
    INNER JOIN items i ON c.id = i.category 
    ORDER BY RAND() 
) AS shuffled_items 
GROUP BY cid 

Beachten Sie, dass, wenn eine Abfrage sowohl GROUP BY und ORDER BY Klausel hat, wird die Gruppierung vor der Sortierung durchgeführt. Aus diesem Grund habe ich zwei Abfragen verwendet: Die erste sortiert die Ergebnisse, die zweite gruppiert die Ergebnisse.

Ich verstehe, dass diese Abfrage kein Rennen gewinnen wird. Ich bin offen für Vorschläge.

+0

Obige Abfrage funktioniert nach ein paar Korrekturen: 'SELECT * FROM ( SELECT c.id als cid, c.category, i.id, i.Name FROM Kategorien c INNER JOIN Artikel i ON c.id = i.category ORDER BY RAND() ) AS ShuffeledItems GROUP BY ShuffeledItems.cid' – rzymek

+0

Hm, diese überarbeitete Abfrage etwa 1500 Zeilen für mich zurückkehrt – djt

+0

@ Salman: Ja, ich bin mir nicht sicher, was ich sagen soll. Ich versuche es auf meiner DB und es gibt etwa 1500 Zeilen, und nicht die 7. – djt

0

Bitte beachten Sie: Im folgenden Beispiel gehe ich davon aus, dass Ihre Tabelle "Elemente" und nicht "Elemente" heißt, weil Sie auch angegeben haben, dass die andere Tabelle "Kategorien" (zweiter Tabellenname nicht groß geschrieben) hat.

Die SQL für das, was Sie grob tun wollen würde:

`SELECT items.id AS item_id, 
items.name AS item_name, 
items.category AS item_category_id, 
categories.id AS category_id, 
categories.category AS category_name 
FROM items, category 
WHERE items.category = categories.id 
ORDER BY rand() 
LIMIT 1` 
+0

Diese Abfrage nur eine Zeile zurückgibt. Ohne LIMIT 1 - alle Artikel aus jeder Kategorie ... – rzymek

+0

@ryzmek, ja, das ist richtig. Dies ist auch, was das OP zufällig verlangt hat. Das OP sagte, und ich zitiere: "Ich möchte eine Abfrage, die 1 zufälliges Element aus jeder Kategorie wählt" –

+0

Meiner Meinung nach erwartet der Autor Abfrage, die 7 Zeilen, ein Rand-Element für jede Kategorie zurückgibt. – rzymek

0

Hier ist eine einfache Lösung. Nehmen wir an, Sie haben diesen Tisch.

id name category 
1 A  1 
2 B  1 
3 C  1 
4 D  2 
5 E  2 
6 F  2 
7 G  3 
8 H  3 
9 I  3 

Verwenden Sie diese Abfrage

select 
    c.id, 
    c.category, 
    (select name from category where category = c.category group by id order by rand() limit 1) as CatName 
from category as c 
group by category 
+0

Dieser Im habe Schwierigkeiten, Sinn zu machen, da es anscheinend keinen Bezug zu den 'items' Tabellen gibt, nur die' categories' Tabelle – djt

+0

@dtj Ich habe kein Schlüsselwort in meiner Abfrage, was verwirrt Sie dann? Ich habe dir ein Beispiel gegeben, aber du kannst dich danach selbst erarbeiten. –

+0

Sind Sie sicher, dass 'GROUP BY' und' RAND() 'zusammen funktionieren und eine Zufallszahl für jede Gruppe ergeben? weil ich es bezweifle. – Sharky

Verwandte Themen