2010-02-19 3 views
8

मुझे यह समस्या है। एक users तालिका कि एक सामाजिक नेटवर्क और friends मेज है कि एक उपयोगकर्ता का नाम और नीचे की तरह एक उपयोगकर्ता के FRIENDNAME शामिल में उपयोगकर्ताओं के उपयोगकर्ता नाम के होते हैं ...ओरेकल एसक्यूएल एक एसक्यूएल स्टेटमेंट कैसे लिखना है जो सत्यापित करता है कि मेरे नेटवर्क में उपयोगकर्ता (यानी दोस्तों या दोस्तों के दोस्त)

username friendname 

John  Thomas 
Chris  James 

को देखते हुए ... मैं एक एसक्यूएल बयान लिखने के लिए कोशिश कर रहा हूँ अगर कोई उपयोगकर्ता मेरे नेटवर्क में होगा। दूसरे शब्दों में क्या वह उपयोगकर्ता मित्र या मित्र का मित्र है?

मैं इस समस्या को हल नाच किया गया है और केवल इस क्वेरी के साथ आ सकता है:

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';  

यह मूल रूप से जाँच लें कि यदि कोई उपयोगकर्ता मेरी मित्र के मित्र है अगर अर्थात सिर्फ अगर झूठी अशक्त लौट आते हैं।

यह पता लगाने की कोशिश कर रहा हूं कि मैं अपने सभी दोस्तों के नेटवर्क के माध्यम से कैसे विस्तार कर सकता हूं। मेरा मतलब सिर्फ मेरे दोस्त का दोस्त नहीं है।

उत्तर

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 

अद्यतन स्तर के रूप में आवश्यक:

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 

इस क्वेरी: आप तीसरी परत मित्र आदि

तो दोस्ती के रिश्ते सममित है के लिए खोज कर सकते हैं, आप निम्न क्वेरी बनाना चाहिए यदि आप अपनी तालिका को denormalize करते हैं तो बहुत तेजी से बनाया जा सकता है: इस तरह दो दो रिकॉर्ड स्टोर करें:

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 

तो फिर तुम सिर्फ dual_friends साथ ऊपर CTE की जगह ले सकता:

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 

, जो इंडेक्स का उपयोग करके और अधिक योग्य, खासकर यदि आप कुछ उचित मूल्य के लिए स्तर तक सीमित कर देगा।

+0

हालांकि ओरेकल तो द्वारा कनेक्ट आपके द्वारा खोजे जा स्तर क्या करेंगे का उपयोग कर – Mark

+0

कि SQL मेरे लिए काम प्रतीत होता है hierarchial प्रश्नों है। ठीक है, इस तालिका उपयोगकर्ता नाम FRIENDNAME दिया कल्पना थॉमस ऐलिस ऐलिस बॉब बॉब जो साथ myname = थॉमस और FRIENDNAME = 'जो' यह दर्शाता है जो थॉमस नेटवर्क है, जो सही नहीं है –

+0

@user में नहीं है कुछ भी नहीं देना है कि एसक्यूएल चल रहा है: है आपकी दोस्ती संबंध सममित? यही है, अगर 'एलिस' थॉमस का दोस्त है, तो 'एलिस' 'ऐलिस' का मित्र भी है? मेरा मानना ​​है कि वह है, लेकिन इसे निर्दिष्ट करना बेहतर है। – Quassnoi

संबंधित मुद्दे