2009-05-29 6 views
5

Dire que j'ai une table qui a des éléments et attributs répertoriés comme,Qu'est-ce qu'une instruction SQL permettant de sélectionner un élément possédant plusieurs attributs dans une liste d'éléments/d'attributs?

frog green 
cat  furry 
frog nice 
cat  4 legs 
frog 4 legs 

Dans la colonne articles que je veux sélectionner des objets uniques qui ont à la fois l'attribut vert et 4 pieds. Je m'attendrais à retrouver juste l'objet grenouille dans ce cas. Quelle est la requête la plus efficace pour cela?

+1

Attributs XML? –

+2

tant de gens mettant en avant de telles bonnes réponses sur une telle question illogique ambigu, bonne chance d'obtenir vos 10 points! –

+0

C'est juste une table sql normale, si elle aide la table s'appelle Pets et elle a deux champs items et attributs. Je ne vois pas en quoi la question est illogique. –

Répondre

8
select item.name 
from item 
where item.attribute in ('4 legs', 'green') 
group by item.name 
having count(distinct item.attribute) = 2 
+0

+1 pour ne pas oublier d'utiliser DISTINCT. L'OP n'a pas donné la définition réelle de la table, donc nous ne savons pas si une paire élément/attribut donnée doit être unique. –

1

select * from table où rien = chose 'grenouille'

bat savoir exatcly ce que vous voulez.

+0

Au 1er j'ai pensé à cela, mais je ne suis pas sûr que l'OP demande "juste ça". ;) +1 de toute façon. –

+1

ha ha ha. 100% correct et 100% faux en même temps je soupçonne – gbn

0

Difficile car ce n'est pas un modèle normalisé. C'est un week-end.

Vous effectuez un filtrage sur plusieurs lignes non connectées. Vous devez donc extraire chaque attribut à tour de rôle, puis faire correspondre les éléments.

SELECT 
    item 
FROM 
    (SELECT 
     item 
    FROM 
     Mytable 
    WHERE 
     attribute = '4 legs') k1 
    JOIN 
    (SELECT 
     item 
    FROM 
     Mytable 
    WHERE 
     attribute = 'green') k2 ON k1.item = k2.item 
+0

Pourquoi dites-vous que la table n'est pas normalisée? –

+0

Premières impressions ... J'aurais dû dire "plus difficile à utiliser pour certains types de requêtes" – gbn

+0

KM a frappé le clou sur la tête aussi dans le commentaire OP – gbn

0

créer deux tables, l'une des éléments et l'un des attributs.
Les éléments peuvent être nom, intAttributeID, où intAttributeID est une référence de clé étrangère à la table Attributes. De cette façon, vous pouvez faire une déclaration en fonction de ce qui vous intéresse.

+0

Pensez à cette table comme la table intermédiaire entre une relation plusieurs-à-plusieurs entre les éléments et les attributs. –

2

La façon la plus efficace de le faire est avec un autojointure:

SELECT * FROM attributes a1 
JOIN attributes a2 USING (item_name) -- e.g. frog 
WHERE a1.value = 'green' AND a2.value = '4 legs'; 

Une autre solution que certaines personnes utilisent un truc avec GROUP BY:

SELECT item_name FROM attributes 
WHERE value IN ('4 legs', 'green') 
GROUP BY item_name 
HAVING COUNT(*) = 2; 

Mais la La solution GROUP BY peut ne pas être aussi efficace qu'un JOIN, selon la marque de SGBDR que vous utilisez. Une méthode peut également évoluer à mesure que le volume de votre table augmente.

+0

Pourquoi diriez-vous que votre première solution est plus efficace? –

+1

@Jason: Mon expérience avec MySQL est que la solution GROUP BY nécessite d'écrire un résultat provisoire sur une table temporaire, ce qui tue généralement les performances. La solution JOIN utilise beaucoup mieux les index. Il peut même utiliser des index de couverture, et ne jamais toucher la table. –

+0

Bon à savoir car j'utilise MySQL. Je me demande ce qui se passerait si je demandais 12 valeurs. –

1
select 
    item, count(*) 
from 
    @temp 
where 
    attribute in ('4 legs','green') 
group by 
    item 
having 
    count(*) = 2 -- this "2" needs to be replaced with however many attributes you have 
0

Mais peut-être cela peut vous aider:

SELECT * 
FROM tbl t1 
INNER JOIN tbl t2 ON t1.Name = t2.Name 
WHERE t1.Attribute = 'green' AND t2.Attribute = '4 legs' 
1

Vous pouvez également interroger chaque attribut séparément, puis les recouper ...

/* 
-- create sample table... 
create table #temp1 
    (item varchar(max), 
    attrib varchar(max)) 

-- populate sample table (SQL 08)... 
insert #temp1 
values ('frog', 'green'), ('cat', 'furry'), ('frog', 'nice'), ('cat', '4 legs'), ('frog', '4 legs') 
*/ 


SELECT item 
FROM #temp1 
WHERE attrib = 'green' 
INTERSECT 
SELECT item 
FROM #temp1 
WHERE attrib = '4 legs' 
0

Si possible, je redessiner. Ce n'est pas quelque chose que vous serez jamais en mesure d'interroger efficacement 12 valeurs en même temps (il faudra 12 joint)

S'il vous plaît lire wikipedia article http://en.wikipedia.org/wiki/Entity-Attribute-Value_model#Downsides

encore jamais vu une base de données qui a utilisé cette modèle qui n'a pas rencontré de graves problèmes de performance finalement. Cette conception est élégante pour les personnes qui ne font pas partie de la base de données, mais elle est généralement le signe d'une base de données mal conçue. Qu'entendez-vous par liste d'articles/d'attributs?

Questions connexes