Как мне создать список, разделенный запятыми, с помощью SQL-запроса?
-
10-07-2019 - |
Вопрос
У меня есть 3 таблицы под названием:
- Приложения (идентификатор, имя)
- Ресурсы (идентификатор, название)
- ApplicationsResources (идентификатор, app_id, resource_id)
Я хочу показать в графическом интерфейсе таблицу всех имен ресурсов.В одной ячейке в каждой строке я хотел бы перечислить все приложения (через запятую) этого ресурса.
Итак, вопрос в том, каков наилучший способ сделать это в SQL, поскольку мне нужно получить все ресурсы, и мне также нужно получить все приложения для каждого ресурса?
Должен ли я сначала запустить select * from resources, а затем выполнить цикл по каждому ресурсу и выполнить отдельный запрос к каждому ресурсу, чтобы получить список приложений для этого ресурса?
Есть ли способ, которым я могу сделать это в одном запросе?
Решение
Нет никакого способа сделать это независимо от базы данных.Итак, вам нужно получить весь набор данных следующим образом:
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
А затем объединить Имя приложения программно при группировке по Повторное имя.
Другие советы
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
Я рекомендую чтение об агрегации / конкатентации строк в Oracle.
Использование 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 Server:
Структура таблицы:
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
- Методы blackbox XML
- Использование среды выполнения Common Language
- Скалярный UDF с рекурсией
- Значение таблицы UDF с циклом WHILE
- Динамический SQL
- Приближение курсора
.
Ненадежные подходы
- Скалярный UDF с расширением обновления t-SQL
- Скалярный UDF с конкатенацией переменных в SELECT
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 ( 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;
Чтобы быть агностиком, откиньтесь назад и плывите на плоскодонке.
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