2014-09-05 7 views
6

में सभी आइटम्स से मेल खाने वाले आईडी का चयन कैसे करें I फ़ायरबर्ड 2.1 का उपयोग कर रहा हूं।फायरबर्ड एक आईडी

वहाँ

एक टेबल है: IDs, Labels

एक ही आईडी के लिए अनेक लेबल नहीं हो सकता है:

10 Peach 
10 Pear 
10 Apple 
11 Apple 
12 Pear 
13 Peach 
13 Apple 

मान लीजिए कि मैं लेबल का एक समूह करते हैं, यानी .: (एप्पल, नाशपाती, आड़ू) ।

मैं उन सभी आईडी को वापस करने के लिए एक ही चयन कैसे लिख सकता हूं जिनमें दिए गए सेट में सभी लेबल शामिल हैं? अधिमानतः मैं अल्पविराम से अलग स्ट्रिंग में सेट निर्दिष्ट करना चाहता हूं, जैसे: ('ऐप्पल', 'पियर', 'पीच') -> यह आईडी = 10.

धन्यवाद!

उत्तर

2

जैसा कि पूछा गया, मैं पिक्लो के उत्तर का अपना सरल संस्करण पोस्ट कर रहा हूं। मैंने इसे अपने फायरबर्ड पर परीक्षण किया है, जो संस्करण 2.5 है, लेकिन ओपी (स्टीव) ने 2.1 पर इसका परीक्षण किया है और यह भी काम करता है।

SELECT id 
FROM table 
WHERE label IN ('Apple', 'Pear', 'Peach') 
GROUP BY id 
HAVING COUNT(DISTINCT label)=3 

यह समाधान pilcrow के रूप में एक ही नुकसान है ... आप, पता करने के लिए आप के लिए कितने मूल्यों लिए देख रहे हैं की जरूरत के रूप में होने = हालत हालत में जहां से मेल खाना चाहिए। इस संबंध में, एड का उत्तर अधिक लचीला है, क्योंकि यह समेकित मूल्य स्ट्रिंग पैरामीटर को विभाजित करता है और मानों की गणना करता है। इसलिए आपको केवल 2 स्थितियों और पायलक्रो उपयोग के बजाय एक पैरामीटर बदलना होगा।

ओटीओएच, अगर प्रभावशीलता चिंता का विषय है, तो मैं सोचूंगा (लेकिन मुझे पूरी तरह से यकीन नहीं है) कि एड का सीटीई दृष्टिकोण फायरबर्ड इंजन द्वारा सुझाए गए एक से कम अनुकूलन हो सकता है। फायरबर्ड प्रश्नों को अनुकूलित करने में बहुत अच्छा है, लेकिन जब आप सीटीई का उपयोग करते हैं तो मैं वास्तव में ऐसा नहीं कर पाता हूं। लेकिन जहां + ग्रुप बाय + हैविंग केवल आईडी (लेबल,) पर एक इंडेक्स होने के द्वारा अनुकूलन योग्य होना चाहिए।

अंत में, यदि निष्पादन समय अपने मामले में चिंता का विषय है, तो आप शायद क्या हो रहा है देखने के लिए कुछ समझाने की योजना है, जो भी समाधान आप चुनते हैं की जरूरत है;)

+0

आपकी (या पायलक्रो) क्वेरी –

+0

में कोई सीटीई ("सामान्य तालिका अभिव्यक्ति") नहीं है, उस टिप्पणी को एड के उत्तर में संदर्भित किया गया था, जो कि अच्छा और लचीला है, लेकिन ** ** सीटीई का उपयोग करता है। मैं इसे स्पष्ट कर दूंगा।धन्यवाद – Frazz

+0

एफबी 2.1 के साथ भी काम करता है। मैं इसे उत्तर के रूप में ले जाऊंगा क्योंकि यह सबसे सरल सवाल है। धन्यवाद! – Steve

2

यह कोड में स्ट्रिंग विभाजित करने के लिए और उसके बाद क्वेरी

SQL> select ID 
CON> from (select ID, count(DISTINCT LABEL) as N_LABELS 
CON>   from T 
CON>   where LABEL in ('Apple', 'Pear', 'Peach') 
CON>   group by 1) D 
CON> where D.N_LABELS >= 3; -- We know a priori we have 3 LABELs 

      ID 
============ 
      10 
+1

क्या होगा अगर (आईडी, लेबल) नहीं अद्वितीय है? मैं subselect में एक DISTINCT जोड़ना होगा ... बस मामले में;) – Frazz

+0

@Frazz, हाँ, धन्यवाद और मिल गया। – pilcrow

+0

मैंने थोड़ी देर में फायरबर्ड का उपयोग नहीं किया है, और मैंने इस प्रकार की क्वेरी करने के लिए इसका उपयोग नहीं किया है। क्या यह फायरबर्ड में SUBSELECT के बिना नहीं किया जा सकता है? मेरा मतलब है ... बाहरी चयन में कहां के बजाय एक हैविंग का उपयोग कर? – Frazz

1

यदि यह एक सहायक संग्रहीत प्रक्रिया है कि प्राथमिक से बुलाया जाएगा का चयन करें तो निम्न पर विचार बनाने के लिए स्वीकार्य है सबसे आसान है।

हेल्पर संग्रहीत प्रक्रिया सीमांकक के साथ एक सीमांकित स्ट्रिंग में लेता है और प्रत्येक सीमांकित स्ट्रिंग

CREATE OR ALTER PROCEDURE SPLIT_BY_DELIMTER (
    WHOLESTRING VARCHAR(10000), 
    SEPARATOR VARCHAR(10)) 
RETURNS (
    ROWID INTEGER, 
    DATA VARCHAR(10000)) 
AS 
DECLARE VARIABLE I INTEGER; 
BEGIN 
    I = 1; 
    WHILE (POSITION(:SEPARATOR IN WHOLESTRING) > 0) DO 
    BEGIN 
     ROWID = I; 
     DATA = TRIM(SUBSTRING(WHOLESTRING FROM 1 FOR POSITION(TRIM(SEPARATOR) IN WHOLESTRING) - 1));   
     SUSPEND;  
     I = I + 1; 
     WHOLESTRING = TRIM(SUBSTRING(WHOLESTRING FROM POSITION(TRIM(SEPARATOR) IN WHOLESTRING) + 1)); 
    END 
    IF (CHAR_LENGTH(WHOLESTRING) > 0) THEN 
    BEGIN 
     ROWID = I; 
     DATA = WHOLESTRING; 
     SUSPEND; 
    END 
END 

नीचे कॉल करने के लिए कोड है के लिए एक पंक्ति देता है, मैं ब्लॉक निष्पादित सीमांकित में गुजर प्रदर्शित करने के लिए उपयोग कर रहा हूँ स्ट्रिंग

EXECUTE BLOCK 
RETURNS (
    LABEL_ID INTEGER) 
AS 
DECLARE VARIABLE PARAMETERS VARCHAR(50); 
BEGIN 
    PARAMETERS = 'Apple,Peach,Pear'; 

    FOR WITH CTE 
    AS (SELECT ROWID, 
      DATA 
     FROM SPLIT_BY_DELIMITER(:PARAMETERS, ',')) 
    SELECT ID 
    FROM TABLE1 
    WHERE LABELS IN (SELECT DATA 
        FROM CTE) 
    GROUP BY ID 
    HAVING COUNT(*) = (SELECT COUNT(*) 
        FROM CTE) 
    INTO :LABEL_ID 
    DO 
    SUSPEND; 
END 
संबंधित मुद्दे