एक ही अल्पविराम से अलग किए गए मान में एक उप-वर्ग में कई परिणामों को मिलाएं


84

मुझे दो टेबल मिली हैं:

TableA
------
ID,
Name

TableB
------
ID,
SomeColumn,
TableA_ID (FK for TableA)

रिश्ते की एक पंक्ति है TableA- कई TableB

अब, मैं इस तरह से एक परिणाम देखना चाहता हूं:

ID     Name      SomeColumn

1.     ABC       X, Y, Z (these are three different rows)
2.     MNO       R, S

यह काम नहीं करेगा (एक उपश्रेणी में कई परिणाम):

SELECT ID,
       Name, 
       (SELECT SomeColumn FROM TableB WHERE F_ID=TableA.ID)
FROM TableA

यह एक तुच्छ समस्या है यदि मैं क्लाइंट की ओर से प्रोसेसिंग करता हूं। लेकिन इसका मतलब यह होगा कि मुझे हर पृष्ठ पर एक्स क्वेरियाँ चलानी होंगी, जहाँ एक्स के परिणामों की संख्या है TableA

ध्यान दें कि मैं केवल एक ग्रुप BY या ऐसा ही कुछ नहीं कर सकता, क्योंकि यह पंक्तियों के लिए कई परिणाम देगा TableA

मुझे यकीन नहीं है कि एक UDF, COALESCE का उपयोग या कुछ इसी तरह काम कर सकता है?

जवाबों:


134

यहां तक ​​कि यह उद्देश्य की पूर्ति करेगा

नमूना डेटा

declare @t table(id int, name varchar(20),somecolumn varchar(MAX))
insert into @t
    select 1,'ABC','X' union all
    select 1,'ABC','Y' union all
    select 1,'ABC','Z' union all
    select 2,'MNO','R' union all
    select 2,'MNO','S'

प्रश्न:

SELECT ID,Name,
    STUFF((SELECT ',' + CAST(T2.SomeColumn AS VARCHAR(MAX))
     FROM @T T2 WHERE T1.id = T2.id AND T1.name = T2.name
     FOR XML PATH('')),1,1,'') SOMECOLUMN
FROM @T T1
GROUP BY id,Name

आउटपुट:

ID  Name    SomeColumn
1   ABC     X,Y,Z
2   MNO     R,S

13
Nt यकीन है कि यह क्यों नहीं उठाया गया है क्योंकि यह एक उपयोगकर्ता फ़ंक्शन की आवश्यकता के बिना समस्या को हल करता है। आप यहाँ व्यक्त किए गए एक ही विचार को codecorner.galanter.net/2009/06/25/… पर देख सकते हैं, जो इस उत्तर को पूर्व निर्धारित करता है और इसलिए "मूल" हो सकता है
पॉल

1
यहाँ भी, यकीन है कि यह उच्च मूल्यांकन क्यों नहीं किया गया है
मार्सेल

1
हाय प्रियंका, क्या आप मुझे बता सकते हैं कि क्या और क्यों "और t1.name = t2.name" खंड यहाँ आवश्यक है?
कोएन

2
यह उत्कृष्ट है। मैं एक UDF फ़ंक्शन को अनुकूलित करने के लिए देख रहा था जैसा कि स्वीकृत उत्तर में सूचीबद्ध था जो मेरे सर्वर को मार रहा था। मैं १०२ सेकंड की खोज से कम से कम १ तक चला गया। निष्पादन योजना की तुलना 2222% -२२% थी, लेकिन यह निष्पादन समय से संबंधित नहीं है ...
टोक्साक २५'११

बस एक चेतावनी है कि आपको उस अग्रणी ',' की आवश्यकता होगी या फिर आप अपने आउटपुट में कोण कोष्ठक के साथ समाप्त करेंगे।
टिम स्कारबोरो

45

1. यूडीएफ बनाएं:

CREATE FUNCTION CombineValues
(
    @FK_ID INT -- The foreign key from TableA which is used 
               -- to fetch corresponding records
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @SomeColumnList VARCHAR(8000);

SELECT @SomeColumnList =
    COALESCE(@SomeColumnList + ', ', '') + CAST(SomeColumn AS varchar(20)) 
FROM TableB C
WHERE C.FK_ID = @FK_ID;

RETURN 
(
    SELECT @SomeColumnList
)
END

2. उपशम में उपयोग करें:

SELECT ID, Name, dbo.CombineValues(FK_ID) FROM TableA

3. यदि आप संग्रहीत प्रक्रिया का उपयोग कर रहे हैं तो आप इस तरह कर सकते हैं:

CREATE PROCEDURE GetCombinedValues
 @FK_ID int
As
BEGIN
DECLARE @SomeColumnList VARCHAR(800)
SELECT @SomeColumnList =
    COALESCE(@SomeColumnList + ', ', '') + CAST(SomeColumn AS varchar(20)) 
FROM TableB
WHERE FK_ID = @FK_ID 

Select *, @SomeColumnList as SelectedIds
    FROM 
        TableA
    WHERE 
        FK_ID = @FK_ID 
END

1
यह अभी भी एक हैक की तरह लगता है। मैं अभी भी उपश्रेणियों का उपयोग कर रहा हूं, इसलिए अभी भी बहुत सारी अतिरिक्त प्रक्रिया चल रही है। मुझे यकीन है कि एक बेहतर समाधान मौजूद है (तालिका पुनर्गठन, या समस्या को देखने का एक और तरीका)।
डॉनी थॉमस

1
मैं इसे हैक नहीं कहूंगा। यह एक कर्सर की तुलना में अधिक कुशल होगा, और इसमें उस ओवरहेड का अभाव है जो डेटा के साथ एक अस्थायी तालिका बनाने के लिए आवश्यक होगा, जिस तरह से आप इसे चाहते हैं।
स्कॉट लॉरेंस

1
शर्म की बात है कि कॉलम पैरामीटर नहीं हो सकते। यह खड़ा है के रूप में आप हर बच्चे के रिश्ते के लिए एक समारोह बनाने की आवश्यकता होगी!
जॉन पॉल जोन्स

1
यह ठीक है - मुझे केवल इन विशेष स्तंभों को संयोजित करने की आवश्यकता है। बाकी 'पारंपरिक' जोड़ हैं।
डॉनी थॉमस

मुझे इस पद्धति के बिना ऐसा करने का सबसे अच्छा तरीका याद नहीं है।
एएफ।

11

मुझे लगता है कि आप COALESCE के साथ सही रास्ते पर हैं। कॉमा-सीमांकित स्ट्रिंग के निर्माण के उदाहरण के लिए यहां देखें:

http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string


2
बहुत बढ़िया! मैंने कुछ लिंक को COALESCE पर चर्चा करते हुए देखा था, लेकिन उनमें ट्रिगर्स के साथ UDFs बनाना शामिल था। आपके द्वारा सबमिट किया गया लिंक एक एकल चयन विवरण के साथ कुंजी है। मैं सही समाधान के साथ एक उत्तर जोड़ रहा हूं, ताकि दूसरों को ढूंढना आसान हो। धन्यवाद!
डॉनी थॉमस

1
हाय बेन, मुझे लगता है कि उत्तर को थोड़ा और विस्तार की आवश्यकता है, अर्थात् यूडीएफ कैसे बनाएं, आदि। एक बार जब मैं यह पता लगाता हूं, तो मैं समाधान को सामुदायिक संपादन योग्य उत्तर के रूप में जोड़ूंगा। कृपया इसे संपादित करने के लिए स्वतंत्र महसूस करें, जिसके बाद मैं इसे उत्तर के रूप में स्वीकार करूंगा। गलतफहमी के लिए खेद है।
डॉनी थॉमस

11

MySQL में एक group_concat फ़ंक्शन होता है जो आपके द्वारा मांगे जाने पर वापस आएगा।

SELECT TableA.ID, TableA.Name, group_concat(TableB.SomeColumn) 
as SomColumnGroup FROM TableA LEFT JOIN TableB ON 
TableB.TableA_ID = TableA.ID

1
यदि SQL सर्वर में एक समान फ़ंक्शन होता, तो यह सही होता। जैसा कि यह खड़ा है, मैं बेन के समाधान का उपयोग एक साथ हथौड़ा मारने के लिए कर रहा हूं जो मैं चाहता हूं।
डॉनी थॉमस

0

अधिक सटीक प्रतिक्रिया के लिए आपको कुछ और विवरण प्रदान करने की आवश्यकता हो सकती है।

चूंकि आपका डेटासेट एक तरह का संकीर्ण लगता है, इसलिए आप प्रति पंक्ति एक पंक्ति का उपयोग करने और क्लाइंट पर पोस्ट-प्रोसेसिंग करने पर विचार कर सकते हैं।

तो अगर आप वास्तव में सर्वर को काम करने के लिए देख रहे हैं, तो परिणाम की तरह सेट करें

ID       Name       SomeColumn
1        ABC        X
1        ABC        Y
1        ABC        Z
2        MNO        R
2        MNO        S

कौन सा कोर्स आईडी पर एक सरल आईएनएन शामिल है

जब आपके पास क्लाइंट पर परिणाम वापस आ जाता है, तो CurrentName नामक एक वैरिएबल बनाए रखें और जब आप ऐसा करना चाहते हैं तो उपयोगी चीज़ में SomeColumn एकत्रित करना बंद करने के लिए ट्रिगर के रूप में उपयोग करें।


मैंने इसके बारे में सोचा था, लेकिन अगर यह एक सुरुचिपूर्ण समाधान है, तो मुझे यकीन नहीं था - मैं चाहूंगा कि SQL सर्वर ठीक से निर्मित परिणाम लौटाए, न कि कुछ और जिसे आगे संसाधित करने की आवश्यकता होगी। क्या आपको अतिरिक्त विवरण की आवश्यकता होगी? मैंने टेबल संरचना को सरल बनाया है, लेकिन मुझे लगता है कि आपको मिल गया है।
डॉनी थॉमस

0

मान लें कि आपके पास केवल तालिका एक पर खंड है इसलिए एक संग्रहीत प्रक्रिया बनाएं:

SELECT Id, Name From tableA WHERE ...

SELECT tableA.Id AS ParentId, Somecolumn 
FROM tableA INNER JOIN tableB on TableA.Id = TableB.F_Id 
WHERE ...

फिर इसके साथ एक DataSet ds भरें। फिर

ds.Relations.Add("foo", ds.Tables[0].Columns("Id"), ds.Tables[1].Columns("ParentId"));

अंत में आप उस पृष्ठ में एक पुनरावर्तक जोड़ सकते हैं जो हर पंक्ति के लिए अल्पविराम लगाता है

 <asp:DataList ID="Subcategories" DataKeyField="ParentCatId" 
DataSource='<%# Container.DataItem.CreateChildView("foo") %>' RepeatColumns="1"
 RepeatDirection="Horizontal" ItemStyle-HorizontalAlign="left" ItemStyle-VerticalAlign="top" 
runat="server" >

इस तरह से आप इसे क्लाइंट साइड में करेंगे, लेकिन केवल एक क्वेरी के साथ, डेटाबेस और फ्रंटएंड के बीच न्यूनतम डेटा पास करेंगे


0

मैं समाधान priyanka.sarkar का उल्लेख करने की कोशिश की और काफी ओपी के रूप में यह काम नहीं कर पाया। यहाँ समाधान मैं के साथ समाप्त हो गया है:

SELECT ID, 
        SUBSTRING((
            SELECT ',' + T2.SomeColumn
            FROM  @T T2 
            WHERE WHERE T1.id = T2.id
            FOR XML PATH('')), 2, 1000000)
    FROM @T T1
GROUP BY ID

-1

नीचे समाधान:

SELECT GROUP_CONCAT(field_attr_best_weekday_value)as RAVI
FROM content_field_attr_best_weekday LEFT JOIN content_type_attraction
    on content_field_attr_best_weekday.nid = content_type_attraction.nid
GROUP BY content_field_attr_best_weekday.nid

इसका उपयोग करें, आप जॉइन को भी बदल सकते हैं


-1
SELECT t.ID, 
       t.NAME, 
       (SELECT t1.SOMECOLUMN 
        FROM   TABLEB t1 
        WHERE  t1.F_ID = T.TABLEA.ID) 
FROM   TABLEA t; 

यह सब क्वेरी का उपयोग करके अलग-अलग तालिका से चयन करने के लिए काम करेगा।


-1

मैंने सभी उत्तरों की समीक्षा की है। मुझे लगता है कि डेटाबेस प्रविष्टि में होना चाहिए:

ID     Name      SomeColumn
1.     ABC       ,X,Y Z (these are three different rows)
2.     MNO       ,R,S

अल्पविराम पिछले अंत में होना चाहिए और जैसे खोज करना चाहिए %,X,%

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.