دمج نتائج متعددة في استعلام فرعي في قيمة واحدة مفصولة بفواصل

StackOverflow https://stackoverflow.com/questions/111341

  •  02-07-2019
  •  | 
  •  

سؤال

لقد حصلت على جدولين:

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

هذه مشكلة تافهة إذا قمت بالمعالجة من جانب العميل.ولكن هذا يعني أنه سيتعين علي تشغيل استعلامات X في كل صفحة، حيث X هو عدد نتائج البحث TableA.

لاحظ أنه لا يمكنني ببساطة إجراء عملية GROUP BY أو شيء مشابه، حيث إنها ستعرض نتائج متعددة لصفوف من TableA.

لست متأكدًا مما إذا كان UDF، باستخدام COALESCE أو شيء مشابه قد يعمل؟

هل كانت مفيدة؟

المحلول 2

1.إنشاء UDF:

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

نصائح أخرى

وحتى هذا سوف يخدم هذا الغرض

بيانات العينة

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

أعتقد أنك على الطريق الصحيح مع COALESCE.انظر هنا للحصول على مثال لبناء سلسلة مفصولة بفواصل:

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

في 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

قد تحتاج إلى تقديم بعض التفاصيل الإضافية للحصول على إجابة أكثر دقة.

نظرًا لأن مجموعة البيانات الخاصة بك تبدو ضيقة نوعًا ما، فقد تفكر في استخدام صف لكل نتيجة وإجراء المعالجة اللاحقة على العميل.

لذا، إذا كنت تتطلع حقًا إلى جعل الخادم يقوم بالعمل، فارجع مجموعة نتائج مثل

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

وهو بالطبع عبارة عن INNER JOIN بسيط على المعرف

بمجرد حصولك على مجموعة النتائج مرة أخرى لدى العميل، احتفظ بمتغير يسمى CurrentName واستخدمه كمحفز عندما تتوقف عن تجميع SomeColumn في الشيء المفيد الذي تريده أن يفعله.

بافتراض أن لديك فقط عبارات WHERE في الجدول A، قم بإنشاء إجراء مخزن وبالتالي:

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" >

بهذه الطريقة ستفعل ذلك من جانب العميل ولكن باستخدام استعلام واحد فقط، وتمرير الحد الأدنى من البيانات بين قاعدة البيانات والواجهة الأمامية

لقد جربت الحل الذي ذكره priyanka.sarkar ولم ينجح تمامًا كما طلب OP.إليك الحل الذي انتهى بي الأمر إليه:

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

الحل أدناه:

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

استخدم هذا، يمكنك أيضًا تغيير عمليات الانضمام

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

سيعمل هذا على الاختيار من جدول مختلف باستخدام الاستعلام الفرعي.

لقد راجعت جميع الإجابات.أعتقد أن إدراج قاعدة البيانات يجب أن يكون مثل:

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

يجب أن تكون الفاصلة في النهاية السابقة وقم بالبحث عن طريق الإعجاب %,X,%

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top