2009-05-29 13 views
5

Decir que tengo una tabla que tiene los elementos y atributos que figuran como,¿Qué es una declaración de SQL para seleccionar un elemento que tiene varios atributos en una lista de elementos/atributos?

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

la columna Elementos Quiero seleccionar objetos únicos que tienen el atributo verde y 4 patas. Esperaría recuperar solo el objeto rana en este caso. ¿Cuál es la consulta más eficiente para hacer esto?

+1

¿Qué quiere decir con la lista de elementos/atributos? Atributos XML? –

+2

tanta gente poniendo adelante tan buenas respuestas en una pregunta ilógica tan ambigua, buena suerte conseguir sus 10 puntos! –

+0

Es sólo una tabla de SQL normal, si ayuda a la mesa se llama mascotas y tiene dos elementos campos y atributos. No veo cómo la pregunta es ilógica. –

Respuesta

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 para recordar el uso de DISTINCT. El OP no dio la definición de tabla real, por lo que no sabemos si un par de elemento/atributo determinado debe ser único. –

1

seleccione * de la tabla donde lo = 'rana'

no hay nada como saber exatcly lo que quiere.

+0

Al principio pensé en eso, pero no estoy seguro de que el OP esté preguntando "solo eso". ;) +1 de todos modos. –

+1

ja ja ja. 100% correcto y 100% incorrecto al mismo tiempo sospecho – gbn

0

duro porque no es un modelo normalizado. Es un fin de semana.

que está filtrando a través de múltiples filas sin conexión, por lo que tendría que extraer cada atributo a su vez y luego coincidir artículos.

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

¿Por qué dices que la tabla no está normalizada? –

+0

Primeras impresiones ... Debería haber dicho "más difícil de usar para algunos tipos de consultas" – gbn

+0

KM golpeó el clavo en la cabeza también en comentario en OP – gbn

0

crear dos tablas, uno de los elementos y uno de los atributos.
artículos se podían nombrar, intAttributeID, donde intAttributeID es una referencia clave externa a la tabla de atributos. De esta forma, puede hacer una declaración selectiva basada en lo que sea que le interese.

+0

Piense en esta tabla como la tabla intermedia entre una relación de muchos a muchos entre elementos y atributos. –

2

La forma más eficaz de hacerlo es con una autocombinación:

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

Otra solución que utilizan algunas personas es un truco con GROUP BY:

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

Pero el La solución GROUP BY puede no ser tan eficiente como JOIN, dependiendo de la marca de RDBMS que use. Además, un método puede escalarse mejor a medida que crece el volumen en su mesa.

+0

¿Por qué diría que su primera solución es más eficiente? –

+1

@Jason: Mi experiencia con MySQL es que la solución GROUP BY requiere escribir un resultado provisional en una tabla temporal, lo que generalmente mata el rendimiento. La solución JOIN emplea índices mucho mejor. Incluso puede usar índices de cobertura y nunca tocar la mesa. –

+0

Es bueno saber que estoy usando MySQL. Me pregunto qué pasaría si estuviera consultando sobre 12 valores. –

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

Pero tal vez esto puede ayudar a:

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

También puede consultar cada atributo por separado, y luego se cruzan ellos ...

/* 
-- 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 es posible, me gustaría rediseñar. Esto no es algo que tendrá que ser capaz de consultar de manera efectiva 12 valores en al mismo tiempo en (se requerirá 12 se une a)

Lea este artículo de Wikipedia http://en.wikipedia.org/wiki/Entity-Attribute-Value_model#Downsides

Nunca

visto una base de datos todavía que utiliza este modelo que finalmente no tuvo problemas de rendimiento serio. Este diseño se ve elegante para las personas que no son de base de datos, pero en realidad es generalmente un signo de una base de datos mal diseñada.

Cuestiones relacionadas