2008-10-02 20 views
10

varsayalım İki sütunlu bir "etiketleri" tablosu var Simülasyonu. Her satır, bir içerik parçasına atanan bir etiketi temsil eder.SQL sorgusu: <strong>TagId</strong> ve <strong>ContentID</strong>: bir "AND" birkaç satır üzerinde yerine alt sorgulama

: Ben bana tagids 334, 338 ile etiketlenmiş içeriğin her parçasının ContentID verecek sorgu ve 342.

bu olurdu yapmak "kolay" yolu (yalancı kod) istiyorum Bununla birlikte, bağırsak bana bunu yapmanın daha iyi, daha hızlı, daha genişletilebilir bir yolu olduğunu söyledi. Örneğin, 12 etiketin kesişimini bulmam gerekirse? Bu hızla korkunçlaşabilir. Herhangi bir fikir?

EDIT: Bu, aynı zamanda this excellent blog post'da da kapsanır. i düşünebilirsiniz

cevap

24
SELECT contentID 
FROM tags 
WHERE tagID in (334, 338, 342) 
GROUP BY contentID 
HAVING COUNT(DISTINCT tagID) = 3 


--In general 
SELECT contentID 
FROM tags 
WHERE tagID in (...) --taglist 
GROUP BY contentID 
HAVING COUNT(DISTINCT tagID) = ... --tagcount 
+0

İşte bu kadar. Tagid, contentid benzersiz olsa da, belki de DISTRINCT, COUNT (DISTINCT tagID) – tzot

+0

Çok akıllı bir çözümde gerekli değildir, ancak SQL2000 yüklememizde bir ince ayar gerektirir. Seçme ifadesinde bir araya sahip olmadan "sahip olma" özelliğini kullanamayız. Etrafında çalışmak için yeterince kolay. –

+0

Bu, Oracle'ın yanı sıra MySQL'de de çalışır mı? –

1

tek alternatif yoludur:

select a.contentid from tags a 
inner join tags b on a.contentid = b.contentid and b.tagid=334 
inner join tags c on a.contentid = c.contentid and c.tagid=342 
where a.tagid=338 
-1

SQL ne tür? MS SQL Server, Oracle, MySQL? Bu daha iyi olup olmadığını bilmiyorum

select contentid from tags where tagid IN (334,338,342) 
+1

Hayır, bu 3 etiketdeki tüm makaleleri verir, aynı 3 etikete sahip tüm makaleleri istiyor – albertein

+0

Evet, haklısın, David B çivilenmiş. – Meff

0

ama

select contentid from tags where tagid = 334 
intersect 
select contentid from tags where tagid = 338 
intersect 
select contentid from tags where tagid = 342 

Sen onu inşa etmesi gerekir daha sürdürülebilir olabilir: SQL Server

bu denk değildir Dinamik olarak, orijinal çözümünüz kadar kötü olmaz.

2

Çok büyük bir nesne ve etiketler veritabanında benim için çok daha hızlı çalışan bir çözüm. Bu üç etiketli bir kesişim için bir örnektir. Sadece zincirleri birçok aynı nesneyi göstermek için nesne etiketi tablosunun (objtags) üzerine katılır ve WHERE fıkrada etiketi kimlikleri öngörmektedir: Bu hızlı çalışır neden

SELECT w0.objid 

FROM  objtags t0 
INNER JOIN objtags t1 ON t1.objid=t0.objid 
INNER JOIN objtags t2 ON t2.objid=t1.objid 

WHERE t0.tagid=512 
    AND t1.tagid=256 
    AND t2.tagid=128 

hiçbir fikrim yok. MusicBrainz sunucusundaki arama kodundan ilham aldı. Postgres'de bunu yaparken, genellikle HAVING COUNT(...) çözümü üzerinden ~ 8-10x hızlanma elde ediyorum.

+0

Üç değerin de geçerli olup olmadığını belirlemek için kümeleme yerine kümeleme kesişimini kullanıyorsunuz. Daha az thrashing. Bu muhteşem, keşke bunu düşünürdüm. –

İlgili konular