這種類型的轉換被稱爲支點。你沒有指定你正在使用的數據庫,所以我將提供SQL Server和MySQL的答案。
SQL服務器:如果您正在使用SQL Server 2005+就可以實現PIVOT
功能。
如果您有已知數量的值要轉換爲列,那麼您可以硬編碼查詢。
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;
請參閱SQL Fiddle with Demo。
但是,如果您有一個未知數的status
值,那麼您將需要使用動態sql在運行時生成列的列表。
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)
參見SQL Fiddle with Demo
這還可以使用具有的情況下表達的聚集函數寫爲:
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
參見SQL Fiddle with Demo
MySQL的:此數據庫做es沒有支點函數,所以你將不得不使用聚合函數和CASE
表達式。它也沒有窗口函數,所以你將不得不稍微改變查詢到以下幾點:
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;
見SQL Fiddle with Demo
然後,如果你需要在MySQL中的動態解決方案,你將不得不使用準備語句生成SQL字符串來執行:
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;
見SQL Fiddle with Demo。
結果是所有查詢相同的兩個數據庫:
| TYPENAME | TOTAL | DEPLOYED | INVENTORY | SHIPPED |
-----------------------------------------------------
| Desktop | 2 | 1 | 1 | 0 |
| Laptop | 1 | 0 | 0 | 1 |
| Server | 1 | 1 | 0 | 0 |
您正在使用什麼RDBMS? – Taryn
(75,56,50)部署值從哪裏來?它們不會出現在您的數據中。 –
這對我來說目前沒什麼意義 您是否有一些示例,瞭解您的表格中的內容,以及一些實際行... 表格之間必須有一些共同點作爲參考將它們鏈接在一起......如果你提供了這個細節,我會去看看它。 –