Как создать список через запятую, используя SQL-запрос?
У меня есть 3 таблицы:
- Приложения (id, name)
- Ресурсы (id, name)
- ApplicationsResources (id, app_id, resource_id)
Я хочу показать в GUI таблицу всех имен ресурсов. В одной ячейке каждой строки я хотел бы указать все приложения (разделенные запятыми) этого ресурса.
Итак, вопрос в том, что лучший способ сделать это в SQL, поскольку мне нужно получить все ресурсы, и мне также нужно получить все приложения для каждого ресурса?
Сначала я запускаю выбор * из ресурсов, а затем прохожу через каждый ресурс и делаю отдельный запрос на ресурс, чтобы получить список приложений для этого ресурса?
Есть ли способ сделать это в одном запросе?
Ответы
Ответ 1
Невозможно сделать это с помощью DB-agnostic.
Поэтому вам нужно получить весь набор данных следующим образом:
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
И затем соедините AppName программно при группировке по ResName.
Ответ 2
MySQL
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 Server (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 Server (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
оракул
Я рекомендую прочитать об агрегации/конкатенации строк в Oracle.
Ответ 3
Использование 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
Ответ 4
Я не знаю, есть ли какое-либо решение для этого в агностическом режиме базы данных, так как вам, скорее всего, понадобится какая-то форма манипуляции с строкой, и они обычно различаются между поставщиками.
Для 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
для перечисления подэлементов (приложений для данного ресурса) в виде списка, разделенного запятыми.
Марк
Ответ 5
Я считаю, что вы хотите:
SELECT ItemName, GROUP_CONCAT(DepartmentId) FROM table_name GROUP BY ItemName
Если вы используете MySQL
Ссылка
Ответ 6
Предполагая SQL Server:
Структура таблицы:
CREATE TABLE [dbo].[item_dept](
[ItemName] char(20) NULL,
[DepartmentID] int NULL
)
Query:
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
Ответ 7
Я думаю, что мы могли бы написать следующим образом, чтобы получить (ниже код - просто пример, пожалуйста, измените по мере необходимости):
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
Ответ 8
Из следующая версия 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.
Ответ 9
MySQL
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 Server
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;
Oracle
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;
Ответ 10
Чтобы быть агностиком, откиньтесь назад и punt.
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 - тот же, что и в последний раз.
Ответ 11
Это будет сделано в SQL Server:
DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' ,'') + Convert(nvarchar(8),DepartmentId)
FROM Table
SELECT @listStr