2009-05-29 13 views
5

Say mam tabelę, która zawiera elementy i atrybuty wymienione podobnychCo to jest instrukcja SQL, aby wybrać element, który ma kilka atrybutów na liście elementów/atrybutów?

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

Z kolumny pozycji Chcę wybrać unikatowe obiekty, które mają zarówno atrybut zielony i 4 nogi. Spodziewałbym się, że w tym przypadku otrzymam tylko obiekt żaby. Jakie jest najbardziej wydajne zapytanie, aby to zrobić?

+1

Co masz na myśli na podstawie listy przedmiotów/atrybutów? Atrybuty XML? –

+2

tak wiele osób przedstawia tak dobre odpowiedzi na tak niejednoznaczne, nielogiczne pytanie, na szczęście zdobywając 10 punktów! –

+0

Jest to po prostu normalna tabela sql, jeśli pomaga tabeli o nazwie Zwierzęta i ma dwa pola elementów i atrybutów. Nie widzę, jak pytanie jest nielogiczne. –

Odpowiedz

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 za zapamiętanie użycia DISTINCT. OP nie podał faktycznej definicji tabeli, więc nie wiemy, czy dana para elementów/atrybutów musi być unikalna. –

1

select * z tabeli gdzie rzeczą = 'żaba'

nic nie przebije wiedząc exatcly co chcesz.

+0

Na 1 myślałem o tym, ale nie jestem pewien, czy OP pyta "właśnie to". ;) +1 mimo to. –

+1

ha ha ha. 100% poprawne i 100% błędne w tym samym czasie. Podejrzewam, że – gbn

0

Trudno, ponieważ nie jest to model znormalizowany. To weekend.

Filtrowanie obejmuje wiele niepołączonych wierszy, dlatego należy wyodrębnić każdy z atrybutów po kolei, a następnie dopasować elementy.

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

Dlaczego nie normalizujesz tabeli? –

+0

Pierwsze wrażenia ... Powinienem był powiedzieć "trudniejsze do zastosowania w przypadku niektórych zapytań" – gbn

+0

KM również uderzył w gwóźdź w komentarzu na temat OP – gbn

0

utworzyć dwie tabele, jeden z elementów i jeden z atrybutów.
Elementy mogą być nazwą, intAttributeID, gdzie intAttributeID to odwołanie do klucza obcego do tabeli atrybutów. W ten sposób możesz dokonać wyboru na podstawie tego, co cię interesuje.

+0

Pomyśl o tej tabeli jako o tabeli pośredniej między relacją wiele do wielu między przedmiotami a atrybutami. –

2

Najbardziej skutecznym sposobem na to jest z samosprzężenie:

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

Innym rozwiązaniem, które niektórzy ludzie używają to sztuczka z GROUP BY:

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

ale Rozwiązanie GROUP BY może nie być tak wydajne jak JOIN, w zależności od marki używanego RDBMS. Również jedna metoda może być lepiej skalowana, ponieważ zwiększa się objętość w twoim stole.

+0

Dlaczego powiedziałbyś, że twoje pierwsze rozwiązanie jest bardziej wydajne? –

+1

@Jason: Moje doświadczenie z MySQL polega na tym, że rozwiązanie GROUP BY wymaga zapisania wyniku tymczasowego w tabeli tymczasowej, która zazwyczaj powoduje utratę wydajności. Rozwiązanie JOIN znacznie lepiej wykorzystuje indeksy. Może nawet używać indeksów pokrycia i nigdy nie dotykać stołu. –

+0

Dobrze wiedzieć, ponieważ używam MySQL. Zastanawiam się, co by się stało, gdybym zapytał o 12 wartości. –

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

Ale może to może pomóc:

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

Można również zapytać każdego atrybutu oddzielnie, a następnie przecina je ...

/* 
-- 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

Jeśli to możliwe, chciałbym przeprojektować. To nie jest coś, co będzie kiedykolwiek w stanie skutecznie kwerendy 12 wartości w tym samym czasie na (będzie to wymagało 12 przyłącza)

Proszę przeczytać ten wikipedia artykuł http://en.wikipedia.org/wiki/Entity-Attribute-Value_model#Downsides

nigdy nie widział jeszcze bazy danych, która używana ta model, który ostatecznie nie napotkał poważnych problemów z wydajnością. Ten projekt wygląda elegancko dla osób nie będących bazami danych, ale w rzeczywistości jest zwykle oznaką źle zaprojektowanej bazy danych.

Powiązane problemy