2016-07-30 27 views
5

PostgreSQL veritabanında c1, c2 ... cn sütunları bulunan bir tablom var. Her satırı, v1, v2 ... vn değerlerinin bir tuple karşılaştırmasını yapan bir sorgu çalıştırmak istiyorum. Sorgu tam eşleşme dönmemesi ancak değer vektörü v benzerlik azalan sipariş satırların listesini dönmelidirSQL: Tam olarak eşleşmeyen satırları bulun ancak tam olarak değil

Örnek:.

tablo içeren spor kayıtlar:

1,USA,basketball,1956 
2,Sweden,basketball,1998 
3,Sweden,skating,1998 
4,Switzerland,golf,2001 

Şimdi zaman V = (İsveç, basketbol, ​​1998) ile bu tabloya karşı bir sorgu çalıştırıyorum, bu vektörle benzerlik gösteren tüm kayıtları almak, eşleşen sütun sayısına göre sıralamaya göre sıralamak istiyorum:

2,Sweden,basketball,1998 --> 3 columns match 
3,Sweden,skating,1998 --> 2 columns match 
1,USA,basketball,1956 --> 1 column matches 

Satır 4 hiç eşleşmediğinden döndürülmedi.

Düzenleme: Tüm sütunlar eşit derecede önemlidir. Her ne kadar gerçekten düşündüğümde, her bir sütuna farklı bir ağırlık faktörü de verebilirsem hoş bir eklenti olurdu.

Satırları bir milyon satırla çalıştırdığımda bile, makul bir süre içinde döndürecek olası bir SQL sorgusu var mı?

Böyle bir sorgu nasıl görünebilir?

+1

İyi soru IMHO – objectNotFound

+1

Soru: eşleşen satırları sıralama söz konusu olduğunda her sütun eşit ağırlığa sahip mi? – objectNotFound

+0

objectNotFound, soru için teşekkürler, ağırlıklar hakkındaki düzenlememi görün. –

cevap

2
SELECT * FROM countries 

WHERE country = 'sweden' 
OR sport = 'basketball' 
OR year = 1998 

ORDER BY 
cast(country = 'sweden' AS integer) + 
cast(sport = 'basketball' as integer) + 
cast(year = 1998 as integer) DESC 

Güzel değil, ama iyi. Boole ifadelerini tamsayılar olarak atayabilir ve bunları özetleyebilirsiniz.

Bir çoğaltıcı ekleyerek ağırlığı kolayca değiştirebilirsiniz.

cast(sport = 'basketball' as integer) * 5 + 
0

İki satır arasındaki "benzerlik ölçüsü" ni hesaplayan saklı yordam yazdıysanız, bu yardımcı olabilir. Ardından, sorgunuz, ifadenin nerede ve ifadeyle ifade edilmezse, bu yordamın geri dönüş değerine doğrudan başvurabilir.

+0

İlginç! Bu saklı prosedür nasıl görünebilir? –

1

Bu şekilde yapardım ... Vakalarda kullanılan çarpım faktörleri, maçın önemini (ağırlığını) ele alacak ve en yüksek ağırlıkla belirlenen sütunlar için eşleşmeleri olan kayıtların olmasını sağlayacaktır. Diğer sütunlar bu özel kayıtlar için eşleşmiyor olsa bile yukarı çık.

/* 
-- Initial Setup 

-- drop table sport 
create table sport (id int, Country varchar(20) , sport varchar(20) , yr int) 

insert into sport values 
(1,'USA','basketball','1956'), 
(2,'Sweden','basketball','1998'), 
(3,'Sweden','skating','1998'), 
(4,'Switzerland','golf','2001') 

select * from sport 
*/ 


select * , 
     CASE WHEN Country='sweden'  then 1 else 0 end * 100 + 
     CASE WHEN sport='basketball' then 1 else 0 end * 10 + 
     CASE WHEN yr=1998    then 1 else 0 end * 1  as Match 
from sport 
WHERE 
    country = 'sweden' 
OR sport = 'basketball' 
OR yr  = 1998 
ORDER BY Match Desc 
+0

Vay, bu cevap için teşekkürler! –