Что такое оператор SQL для выбора элемента, который имеет несколько атрибутов в списке элементов / атрибутов? - PullRequest
5 голосов
/ 29 мая 2009

Допустим, у меня есть таблица, в которой перечислены элементы и атрибуты, например,

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

В столбце «Предметы» я хочу выбрать уникальные объекты, которые имеют как зеленый, так и 4 ножки. В этом случае я бы ожидал вернуть только объект лягушки. Какой самый эффективный запрос для этого?

Ответы [ 9 ]

9 голосов
/ 29 мая 2009
select  item.name 
from    item 
where   item.attribute in ('4 legs', 'green') 
group by item.name 
having  count(distinct item.attribute) = 2
2 голосов
/ 29 мая 2009

Самый эффективный способ сделать это с самостоятельным соединением:

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

Еще одним решением, которое используют некоторые люди, является трюк с GROUP BY:

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

Но решение GROUP BY может быть не таким эффективным, как JOIN, в зависимости от того, какую марку СУБД вы используете. Также один метод может масштабироваться лучше по мере увеличения объема в вашей таблице.

1 голос
/ 29 мая 2009

Вы также можете запросить каждый атрибут отдельно, а затем пересечь их ...

/*
-- 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'
1 голос
/ 29 мая 2009
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
1 голос
/ 29 мая 2009

выбрать * из таблицы, где вещь = 'лягушка'

ничто не сравнится с знанием того, что вы хотите.

0 голосов
/ 30 мая 2009

Если возможно, я бы изменил дизайн. Это не то, что вы когда-либо сможете эффективно запрашивать 12 значений одновременно (для этого потребуется 12 объединений)

Пожалуйста, прочитайте эту статью в Википедии http://en.wikipedia.org/wiki/Entity-Attribute-Value_model#Downsides

Никогда еще не видел базу данных, в которой использовалась бы эта модель, которая в конечном итоге не сталкивалась с серьезными проблемами с производительностью. Этот дизайн выглядит элегантно для людей, не работающих с базами данных, но на самом деле он обычно является признаком плохо спроектированной базы данных.

0 голосов
/ 29 мая 2009

Но, может быть, это поможет вам:

SELECT * 
FROM tbl t1
INNER JOIN tbl t2 ON t1.Name = t2.Name
WHERE t1.Attribute = 'green' AND t2.Attribute = '4 legs'
0 голосов
/ 29 мая 2009

создать две таблицы, одну из элементов и одну из атрибутов.
Элементами могут быть имя, intAttributeID, где intAttributeID - это ссылка внешнего ключа на таблицу атрибутов Таким образом, вы можете делать операторы выбора, основываясь на том, что вас волнует.

0 голосов
/ 29 мая 2009

Тяжело, потому что это не нормализованная модель. Это выходные.

Вы фильтруете по нескольким несвязанным строкам, поэтому вам придется извлекать каждый атрибут по очереди, а затем сопоставлять элементы.

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
...