2010-02-19 19 views
8

Bu sorunu çözdüğümü doğrulayan bir sql deyimi nasıl yazılır. Bir kullanıcının adını ve aşağıdaki gibi bir kullanıcının FRIENDNAME içerirler bir sosyal ağ ve friends tabloda kullanıcıların kullanıcı adı oluşan users tablo ...Oracle SQL, ağımdaki kullanıcının (yani arkadaşların veya arkadaşların arkadaşının)

username friendname 

John  Thomas 
Chris  James 

Verilen ... Bir SQL deyimi yazmaya çalışıyorum Bir kullanıcı ağımdaysa bu olur. Başka bir deyişle, , kullanıcı arkadaş mı, arkadaş mı?

Bu sorunu gidermek dans ediyoruz ve sadece bu sorgu ile gelebilir: false eğer benim arkadaşımın arkadaşı ise bir kullanıcı yani sadece boş dönerseniz

SELECT f2.username, f2.friendname 
FROM friends f2 
WHERE f2.username IN (
     SELECT f1.friendname 
     FROM friends f1 
     WHERE f1.username = 'Thomas') 
AND f2.friendname <> 'user1' 
AND f2.friendname = 'user2';  

Temelde kontrol edin.

Tüm arkadaş ağım boyunca ilerlemek için nasıl genişleyebileceğimi anlamaya çalışıyorum. Yani sadece arkadaşımın arkadaşı değil. Gerektiğinde düzey

cevap

5
SELECT * 
FROM (
     SELECT username 
     FROM friends 
     START WITH 
       username = 'myname' 
     CONNECT BY 
       friendname = PRIOR username 
       AND level <= 3 
     ) 
WHERE username = 'friendname' 
     AND rownum = 1 

Güncelleme:

WITH q AS 
     (
     SELECT username, friendname 
     FROM friends 
     UNION ALL 
     SELECT friendname, username 
     FROM friends 
     ), 
     f AS 
     (
     SELECT friendname, level 
     FROM q 
     START WITH 
       username = 'Thomas' 
     CONNECT BY NOCYCLE 
       username = PRIOR friendname 
     ) 
SELECT * 
FROM f 
WHERE friendname = 'Jo' 
     AND rownum = 1 

Bu sorgu: vb üçüncü katman arkadaşlar

dostluk ilişkisi simetrik ise arayabilir, aşağıdaki sorguyu yapmalıdır tablonuzu denormalize ederseniz çok daha hızlı yapılabilir: şu şekilde arkadaşlık başına iki kayıt saklayın:

CREATE TABLE dual_friends (orestes NOT NULL, pylades NOT NULL, CONSTRAINT pk_dualfriends_op PRIMARY KEY (orestes, pylades)) ORGANIZATION INDEX 
AS 
SELECT username, friendname 
FROM friends 
UNION ALL 
SELECT friendname, username 
     FROM friends 

Sonra sadece dual_friends yukarıda CTE değiştirebilirsiniz:

WITH f AS 
     (
     SELECT pylades, level 
     FROM dual_friends 
     START WITH 
       orestes = 'Thomas' 
     CONNECT BY NOCYCLE 
       orestes = PRIOR pylades 
       AND level <= 3 
     ) 
SELECT * 
FROM f 
WHERE pylades = 'Jo' 
     AND rownum = 1 

, indeks kullanmak ve bazı makul değere seviyesini sınırlamak, özellikle çok daha verimli olacak.

+0

Ancak oracle O sql iş için beni görünüyor – Mark

+0

sizi aramayan seviyesini yapacak böylece tarafından bağlamak kullanarak Hiyerarşik sorgusu var kullanabilirsiniz. Tamam, kullanıcı adı FRIENDNAME bu tabloyu verilen hayal Thomas Alice Aylin Ali'nin Bob Jo Jo –

+0

@user yanlıştır Thomas ağı içinde değil belirten hiçbir şey vermek = 'Jo' myname = Thomas ve FRIENDNAME o sql çalıştırma: mi arkadaşlık ilişkiniz simetrik mi? Yani, eğer 'Alice' Thomas'ın arkadaşıysa, '' Alice'in '' Alice''in arkadaşı da mı? Onun olduğuna inanıyorum, ama belirtmek daha iyidir. – Quassnoi