Что такое инструкция SQL для выбора элемента, который имеет несколько атрибутов в списке элементов / атрибутов?
-
06-09-2019 - |
Вопрос
Допустим, у меня есть таблица, в которой элементы и атрибуты перечислены следующим образом,
frog green
cat furry
frog nice
cat 4 legs
frog 4 legs
В столбце элементы я хочу выбрать уникальные объекты, которые имеют атрибут green и 4 legs.В этом случае я бы ожидал получить обратно только объект frog.Какой запрос наиболее эффективен для этого?
Решение
select item.name
from item
where item.attribute in ('4 legs', 'green')
group by item.name
having count(distinct item.attribute) = 2
Другие советы
Самый эффективный способ сделать это - с помощью самосоединения:
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, в зависимости от того, какую марку СУБД вы используете.Кроме того, один из методов может лучше масштабироваться по мере увеличения объема вашей таблицы.
выберите * из таблицы, где thing='лягушка'
нет ничего лучше, чем точно знать, чего ты хочешь.
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
Кроме того, можно запросить каждый атрибут отдельно, а затем пересекают их ...
/*
-- 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'
создайте две таблицы, одну из элементов и одну из атрибутов.
Элементами могут быть name, intAttributeID, где intAttributeID - это ссылка на внешний ключ таблицы атрибутов.Таким образом, вы можете выполнить оператор select на основе всего, что вас волнует.
Но, может быть, это поможет вам:
SELECT *
FROM tbl t1
INNER JOIN tbl t2 ON t1.Name = t2.Name
WHERE t1.Attribute = 'green' AND t2.Attribute = '4 legs'
Сложно, потому что это не нормализованная модель. Сегодня выходные.
Вы фильтруете по нескольким несвязанным строкам, поэтому вам придется извлекать каждый атрибут по очереди, а затем сопоставлять элементы.
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
Если возможно, я бы переделал дизайн.Это не то, к чему вы когда-либо сможете эффективно запрашивать 12 значений одновременно (для этого потребуется 12 объединений)
Пожалуйста, прочтите эту статью в Википедии http://en.wikipedia.org/wiki/Entity-Attribute-Value_model#Downsides
Никогда еще не видел базы данных, использующей эту модель, которая в конечном итоге не столкнулась бы с серьезными проблемами производительности.Такой дизайн выглядит элегантно для людей, не имеющих отношения к базам данных, но на самом деле обычно является признаком плохо спроектированной базы данных.