Questo tipo di trasformazione è chiamato un perno. Non hai specificato quale database stai usando, quindi fornirò una risposta per SQL Server e MySQL.
SQL Server: Se si utilizza SQL Server 2005 + è possibile implementare la funzione PIVOT
.
Se si dispone di un numero noto di valori che si desidera convertire in colonne, è possibile codificare manualmente la query.
select typename, total, Deployed, Inventory, shipped
from
(
select count(*) over(partition by t.typename) total,
s.statusname,
t.typename
from assets a
inner join assettypes t
on a.assettype = t.id
inner join assetstatus s
on a.assetstatus = s.id
) d
pivot
(
count(statusname)
for statusname in (Deployed, Inventory, shipped)
) piv;
Vedere SQL Fiddle with Demo.
Ma se si dispone di un numero sconosciuto di valori status
, sarà necessario utilizzare sql dinamico per generare l'elenco di colonne in fase di esecuzione.
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(statusname)
from assetstatus
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT typename, total,' + @cols + ' from
(
select count(*) over(partition by t.typename) total,
s.statusname,
t.typename
from assets a
inner join assettypes t
on a.assettype = t.id
inner join assetstatus s
on a.assetstatus = s.id
) x
pivot
(
count(statusname)
for statusname in (' + @cols + ')
) p '
execute(@query)
Vedi SQL Fiddle with Demo
Questo può anche essere scritta utilizzando una funzione di aggregazione con un caso espressione:
select typename,
total,
sum(case when statusname ='Deployed' then 1 else 0 end) Deployed,
sum(case when statusname ='Inventory' then 1 else 0 end) Inventory,
sum(case when statusname ='Shipped' then 1 else 0 end) Shipped
from
(
select count(*) over(partition by t.typename) total,
s.statusname,
t.typename
from assets a
inner join assettypes t
on a.assettype = t.id
inner join assetstatus s
on a.assetstatus = s.id
) d
group by typename, total
Vedi SQL Fiddle with Demo
MySQL: Questo database fare es non ha una funzione pivot quindi sarà necessario utilizzare la funzione di aggregazione e un'espressione CASE
. Inoltre non hanno funzioni a finestre, in modo da avere a modificare la query leggermente al seguente:
select typename,
total,
sum(case when statusname ='Deployed' then 1 else 0 end) Deployed,
sum(case when statusname ='Inventory' then 1 else 0 end) Inventory,
sum(case when statusname ='Shipped' then 1 else 0 end) Shipped
from
(
select t.typename,
(select count(*)
from assets a1
where a1.assettype = t.id
group by a1.assettype) total,
s.statusname
from assets a
inner join assettypes t
on a.assettype = t.id
inner join assetstatus s
on a.assetstatus = s.id
) d
group by typename, total;
Vedi SQL Fiddle with Demo
Quindi se avete bisogno di una soluzione dinamica in MySQL, si dovrà utilizzare un dichiarazione preparata per generare la stringa SQL da eseguire:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(CASE WHEN statusname = ''',
statusname,
''' THEN 1 else 0 END) AS `',
statusname, '`'
)
) INTO @sql
FROM assetstatus;
SET @sql
= CONCAT('SELECT typename,
total, ', @sql, '
from
(
select t.typename,
(select count(*)
from assets a1
where a1.assettype = t.id
group by a1.assettype) total,
s.statusname
from assets a
inner join assettypes t
on a.assettype = t.id
inner join assetstatus s
on a.assetstatus = s.id
) d
group by typename, total');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Vedi SQL Fiddle with Demo.
Il risultato è lo stesso per tutte le query in entrambi i database:
| TYPENAME | TOTAL | DEPLOYED | INVENTORY | SHIPPED |
-----------------------------------------------------
| Desktop | 2 | 1 | 1 | 0 |
| Laptop | 1 | 0 | 0 | 1 |
| Server | 1 | 1 | 0 | 0 |
Cosa RDBMS stai usando? – Taryn
Da dove provengono i valori (75, 56, 50)? Non appaiono nei tuoi dati. –
Al momento non ha molto senso per me Hai alcuni esempi di ciò che è nelle tue tabelle, alcune righe effettive ... Ci deve essere un po 'di comunanza tra le tabelle come punto di riferimento per collegali insieme ... Se fornisci quel dettaglio, ci provo. –