2009-09-28 8 views
3

J'ai une requête sql qui sélectionne des données de plusieurs tables, mais je veux seulement faire correspondre une seule ligne (sélectionnée au hasard) d'une autre table.Sélection d'une seule ligne (aléatoire) pour une jointure SQL

plus facile de montrer un peu de code, je pense;)

Tableau K (k_id, choisi) Tableau C (C_Id, image) Tableau S (C_Id, date) tableau M est (C_Id , k_id, score)

Toutes les colonnes ID sont des clés primaires, avec des contraintes FK appropriées. Ce que je veux, en anglais, est pour eack row dans K qui a choisi = 1 pour obtenir une ligne aléatoire de C où il existe une ligne dans M avec (K_id, C_id), où le score est supérieur à un compte tenu de la valeur, et où c.image n'est pas nul et il y a une ligne de s avec C_Id

Quelque chose comme:

select k.k_id, c.c_id, m.score 
from k,c,m,s 
where k.selected = 1 
    and m.score > some_value 
    and m.k_id = k.k_id 
    and m.c_id = c.c_id 
    and c.image is not null 
    and s.c_id = c.c_id; 

Le seul problème est le suivant retourne toutes les lignes C qui correspondent aux critères - Je n'en veux qu'un ...

Je peux voir comment le faire en utilisant PL/SQL pour sélectionner tout relevez des lignes dans une collection, puis sélectionnez-en une aléatoire, mais je suis coincé quant à la façon de sélectionner un aléatoire.

Répondre

0

avec l'analyse:

SELECT k_id, c_id, score 
    FROM (SELECT k.k_id, c.c_id, m.score, 
       row_number() over(PARTITION BY k.k_id ORDER BY NULL) rk 
      FROM k, c, m, s 
      WHERE k.selected = 1 
      AND m.score > some_value 
      AND m.k_id = k.k_id 
      AND m.c_id = c.c_id 
      AND c.image IS NOT NULL 
      AND s.c_id = c.c_id) 
WHERE rk = 1 

Cela permet de sélectionner une ligne qui répond à vos critères par k_id. Cela sélectionnera probablement le même ensemble de lignes si vous exécutez la requête plusieurs fois. Si vous voulez plus de hasard (chaque série produit un ensemble différent de lignes), vous devez remplacer ORDER BY NULL par ORDER BY dbms_random.value

+1

ORDER BY NULL ne produira probablement pas un ordre aléatoire. Inpredictable, oui, mais pas au hasard. Les lignes seront (très probablement) retournées dans l'ordre où elles sont stockées dans l'index ou d'où qu'elles soient lues, ce qui pourrait ou non être assez bon pour l'OP. – erikkallen

+0

@erikkallen> Je suis d'accord, j'ai mis à jour ma réponse avec un moyen d'ajouter le caractère aléatoire à l'imprévisibilité:> –

+0

Parfait! - ressemble à PARTITION BY était la clé. Merci. – PaulJWilliams

-1

Je ne suis pas très familier avec Oracle SQL, mais essayez d'utiliser LIMIT random(), si une telle fonction est disponible.

+0

Oracle SQL ne prend pas en charge le mot-clé LIMIT. – APC

+1

Merci, ne le savais pas :) – Marius

+0

Il le fait, il suffit de l'appeler rownum ... et rownum <= x est limite x –

Questions connexes