كيف أقوم بإنشاء قائمة مفصولة بفواصل باستخدام استعلام SQL؟
-
10-07-2019 - |
سؤال
لدي 3 جداول تسمى:
- التطبيقات (المعرف، الاسم)
- الموارد (المعرف، الاسم)
- مصادر التطبيقات (المعرف، app_id، الموارد_id)
أريد أن أعرض على واجهة المستخدم الرسومية جدولًا بجميع أسماء الموارد.في خلية واحدة في كل صف، أود سرد كافة التطبيقات (مفصولة بفواصل) لهذا المورد.
لذا فإن السؤال هو، ما هي أفضل طريقة للقيام بذلك في SQL حيث أحتاج إلى الحصول على جميع الموارد وأحتاج أيضًا إلى الحصول على جميع التطبيقات لكل مورد؟
هل أقوم بتشغيل تحديد * من الموارد أولاً ثم تكرار كل مورد وإجراء استعلام منفصل لكل مورد للحصول على قائمة التطبيقات لهذا المورد؟
هل هناك طريقة يمكنني من خلالها القيام بذلك في استعلام واحد؟
المحلول
لا توجد طريقة للقيام بذلك بطريقة حيادية لقاعدة البيانات.لذلك تحتاج إلى الحصول على مجموعة البيانات بأكملها مثل هذا:
select
r.name as ResName,
a.name as AppName
from
Resouces as r,
Applications as a,
ApplicationsResources as ar
where
ar.app_id = a.id
and ar.resource_id = r.id
ومن ثم ربط اسم التطبيق برمجيا أثناء التجميع حسب ResName.
نصائح أخرى
ماي إس كيو إل
SELECT r.name,
GROUP_CONCAT(a.name SEPARATOR ',')
FROM RESOURCES r
JOIN APPLICATIONSRESOURCES ar ON ar.resource_id = r.id
JOIN APPLICATIONS a ON a.id = ar.app_id
GROUP BY r.name
خادم SQL (2005+)
SELECT r.name,
STUFF((SELECT ','+ a.name
FROM APPLICATIONS a
JOIN APPLICATIONRESOURCES ar ON ar.app_id = a.id
WHERE ar.resource_id = r.id
GROUP BY a.name
FOR XML PATH(''), TYPE).value('.','VARCHAR(max)'), 1, 1, '')
FROM RESOURCES r
خادم SQL (2017+)
SELECT r.name,
STRING_AGG(a.name, ',')
FROM RESOURCES r
JOIN APPLICATIONSRESOURCES ar ON ar.resource_id = r.id
JOIN APPLICATIONS a ON a.id = ar.app_id
GROUP BY r.name
وحي
استخدام COALESCE لإنشاء سلسلة مفصولة بفواصل في SQL Server
http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string
مثال:
DECLARE @EmployeeList varchar(100)
SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') +
CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT @EmployeeList
لا أعرف ما إذا كان هناك أي حل للقيام بذلك بطريقة لا تعتمد على قاعدة البيانات، نظرًا لأنك ستحتاج على الأرجح إلى شكل من أشكال معالجة السلسلة، وعادةً ما يختلف ذلك بين البائعين.
بالنسبة لـ SQL Server 2005 والإصدارات الأحدث، يمكنك استخدام:
SELECT
r.ID, r.Name,
Resources = STUFF(
(SELECT ','+a.Name
FROM dbo.Applications a
INNER JOIN dbo.ApplicationsResources ar ON ar.app_id = a.id
WHERE ar.resource_id = r.id
FOR XML PATH('')), 1, 1, '')
FROM
dbo.Resources r
ويستخدم SQL Server 2005 FOR XML PATH
إنشاء لسرد العناصر الفرعية (التطبيقات الخاصة بمورد معين) كقائمة مفصولة بفواصل.
مارك
أعتقد أن ما تريده هو:
SELECT ItemName, GROUP_CONCAT(DepartmentId) FROM table_name GROUP BY ItemName
إذا كنت تستخدم MySQL
مرجع
بافتراض خادم SQL:
هيكل الجدول:
CREATE TABLE [dbo].[item_dept](
[ItemName] char(20) NULL,
[DepartmentID] int NULL
)
استفسار:
SELECT ItemName,
STUFF((SELECT ',' + rtrim(convert(char(10),DepartmentID))
FROM item_dept b
WHERE a.ItemName = b.ItemName
FOR XML PATH('')),1,1,'') DepartmentID
FROM item_dept a
GROUP BY ItemName
نتائج:
ItemName DepartmentID
item1 21,13,9,36
item2 4,9,44
أعتقد أنه يمكننا الكتابة بالطريقة التالية للاسترداد (الرمز أدناه مجرد مثال، يرجى تعديله حسب الحاجة):
Create FUNCTION dbo.ufnGetEmployeeMultiple(@DepartmentID int)
RETURNS VARCHAR(1000) AS
BEGIN
DECLARE @Employeelist varchar(1000)
SELECT @Employeelist = COALESCE(@Employeelist + ', ', '') + E.LoginID
FROM humanresources.Employee E
Left JOIN humanresources.EmployeeDepartmentHistory H ON
E.BusinessEntityID = H.BusinessEntityID
INNER JOIN HumanResources.Department D ON
H.DepartmentID = D.DepartmentID
Where H.DepartmentID = @DepartmentID
Return @Employeelist
END
SELECT D.name as Department, dbo.ufnGetEmployeeMultiple (D.DepartmentID)as Employees
FROM HumanResources.Department D
SELECT Distinct (D.name) as Department, dbo.ufnGetEmployeeMultiple (D.DepartmentID) as
Employees
FROM HumanResources.Department D
من الإصدار التالي من SQL Server سوف تكون قادرا على القيام به
SELECT r.name,
STRING_AGG(a.name, ',')
FROM RESOURCES r
JOIN APPLICATIONSRESOURCES ar
ON ar.resource_id = r.id
JOIN APPLICATIONS a
ON a.id = ar.app_id
GROUP BY r.name
بالنسبة للإصدارات السابقة من المنتج، توجد مجموعة كبيرة ومتنوعة من الأساليب المختلفة لحل هذه المشكلة.مراجعة ممتازة لهم في المقال: تسلسل قيم الصف في Transact-SQL.
تسلسل القيم عندما يكون عدد العناصر غير معروف
- طريقة CTE العودية
- أساليب الصندوق الأسود XML
- استخدام وقت تشغيل اللغة العامة
- UDF العددية مع العودية
- جدول بقيمة UDF مع حلقة WHILE
- SQL الديناميكية
- نهج المؤشر
.
أساليب غير موثوقة
- Scalar UDF مع ملحق تحديث t-SQL
- UDF عددي مع تسلسل متغير في SELECT
ماي إس كيو إل
SELECT r.name,
GROUP_CONCAT(a.name SEPARATOR ',')
FROM RESOURCES r
JOIN APPLICATIONSRESOURCES ar ON ar.resource_id = r.id
JOIN APPLICATIONS a ON a.id = ar.app_id
GROUP BY r.name
**
خادم MS SQL
SELECT r.name,
STUFF((SELECT ','+ a.name
FROM APPLICATIONS a
JOIN APPLICATIONRESOURCES ar ON ar.app_id = a.id
WHERE ar.resource_id = r.id
GROUP BY a.name
FOR XML PATH(''), TYPE).value('.','VARCHAR(max)'), 1, 1, '')
FROM RESOURCES r
GROUP BY deptno;
وحي
SELECT r.name,
LISTAGG(a.name SEPARATOR ',') WITHIN GROUP (ORDER BY a.name)
FROM RESOURCES r
JOIN APPLICATIONSRESOURCES ar ON ar.resource_id = r.id
JOIN APPLICATIONS a ON a.id = ar.app_id
GROUP BY r.name;
لكي تكون ملحدًا، قم بالتراجع والقفز.
Select a.name as a_name, r.name as r_name
from ApplicationsResource ar, Applications a, Resources r
where a.id = ar.app_id
and r.id = ar.resource_id
order by r.name, a.name;
الآن استخدم لغة برمجة الخادم الخاص بك لتسلسل a_names بينما r_name هو نفسه في المرة الأخيرة.
سيتم ذلك في SQL Server:
DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' ,'') + Convert(nvarchar(8),DepartmentId)
FROM Table
SELECT @listStr