Pergunta

Eu tenho 3 tabelas chamado:

  • Applications (id, nome)
  • Recursos (id, nome)
  • ApplicationsResources (id, app_id, RESOURCE_ID)

Eu quero mostrar em uma GUI uma tabela de todos os nomes de recursos. Em uma célula em cada linha Eu gostaria de listar todas as aplicações (separados por vírgula) desse recurso.

Então a questão é, qual é a melhor maneira de fazer isso em SQL como eu preciso para obter todos os recursos e eu também precisa obter todas as aplicações para cada recurso?

Eu executar um select * from recursos primeiro e depois percorrer cada recurso e fazer uma consulta separada por recurso para obter a lista de aplicativos para esse recurso?

Existe uma maneira eu posso fazer isso em uma consulta?

Foi útil?

Solução

Não há nenhuma maneira de fazê-lo de uma forma DB-agnóstico. Então você precisa para obter o conjunto de dados definido como este:

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

E então concat o AppName programação , enquanto agrupamento por ResName .

Outras dicas

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

A Oracle

Eu recomendo ler sobre cadeia de agregação / concatentation no Oracle .

Usando COALESCE construir delimitado por vírgula de Cordas em SQL Server
http://www.sqlteam.com/article/using -coalesce-to-build-vírgula-delimitado por corda

Exemplo:

DECLARE @EmployeeList varchar(100)

SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') + 
   CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1

SELECT @EmployeeList

Eu não sei se há alguma solução para fazer isso de uma forma de banco de dados agnóstica, já que você provavelmente irá precisar de alguma forma de manipulação de cadeia, e esses são normalmente diferentes entre fornecedores.

Para o SQL Server 2005 e acima, você pode usar:

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

Ele usa o SQL Server 2005 construção FOR XML PATH para listar os subitens (os pedidos de um determinado recurso) como uma lista separada por vírgulas.

Marc

Eu acredito que o que você quer é:

SELECT ItemName, GROUP_CONCAT(DepartmentId) FROM table_name GROUP BY ItemName

Se você estiver usando MySQL

Referência

Assumindo SQL Server:

Estrutura da tabela:

CREATE TABLE [dbo].[item_dept](
    [ItemName] char(20) NULL,
    [DepartmentID] int NULL   
)

Inquérito:

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

Resultado:

ItemName    DepartmentID
item1       21,13,9,36
item2       4,9,44

Eu acho que poderia escrever da seguinte maneira para recuperar (o código abaixo é apenas um exemplo, por favor modifique conforme necessário):

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

A partir próxima versão do SQL Server você será capaz de fazer

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 

Para versões anteriores do produto há muito uma grande variedade de abordagens diferentes para este problema. Uma excelente revisão deles é no artigo: Valores Concatenando fileira em Transact-SQL .

  • A concatenação de valores quando o número de itens não são conhecidos

    • método recursiva CTE
    • Os métodos XML blackbox
    • Usando Common Language Runtime
    • Scalar UDF com recursão
    • Tabela valorizado UDF com um tempo loop
    • Dinâmico SQL
    • O Cursor abordagem
      .
  • abordagens não-confiáveis ??

    • Scalar UDF com extensão atualização t-SQL
    • Scalar UDF com concatenação variável no 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

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;

do 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;

Para ser agnóstico, back drop e 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;

Agora o usuário sua linguagem de programação do servidor para a_names concatenar enquanto r_name é o mesmo que da última vez.

Isso vai fazê-lo em SQL Server:

DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' ,'') + Convert(nvarchar(8),DepartmentId)
FROM Table
SELECT @listStr
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top