我有一个问题一直困扰着我几天。我有一张桌子:
我想将此数据放在另一个表中,该表将Status_ID分组为列。此表包含如下列:
因此,Status_ID 2和3可能会在休假,Status_ID 1午餐等分组
我想过在一个while循环中嵌套一个Case,遍历每一行插入到我的另一个表中。但是,我无法将这些数据从行中的Status_ID插入到现在按其分组的列中。
答案 0 :(得分:2)
不需要WHILE
循环。
SELECT
date,
id,
SUM(CASE WHEN status_id = 1 THEN status_time ELSE 0 END) AS lunch,
SUM(CASE WHEN status_id = 2 THEN status_time ELSE 0 END) AS break,
SUM(CASE WHEN status_id = 3 THEN status_time ELSE 0 END) AS vacation
FROM
My_Table
GROUP BY
date,
id
此外,将status_time
保留在表中是一个错误(除非它是一个非持久的计算列)。您实际上是将相同的数据存储在数据库中的两个位置,这最终会导致不一致。将此数据推送到另一个表中也是如此,其中按状态类型划分时间。不要创建新表来保存数据,使用查询在需要时获取数据。
答案 1 :(得分:0)
这种类型的查询(将值从行转换为列)被命名为pivot query(SQL Server)或crosstab(Access)。
有两种类型的数据透视查询(一般来说):
SQL Server支持这两种类型,但是:
T-SQL(仅限)解决方案:
对于第一种类型(1),从SQL Server 2005开始,您可以使用PIVOT运算符:
SELECT pvt.*
FROM
(
SELECT Date, Id, Status_ID, Status_Time
FROM Table
) src
PIVOT ( SUM(src.Status_Time) FOR src.Status_ID IN ([1], [2], [3]) ) pvt
或
SELECT pvt.Date, pvt.Id, pvt.[1] AS Lunch, pvt.[2] AS [Break], pvt.[3] Vacation
FROM
(
SELECT Date, Id, Status_ID, Status_Time
FROM Table
) src
PIVOT ( SUM(src.Status_Time) FOR src.Status_ID IN ([1], [2], [3]) ) pvt
对于动态数量的列(2),T-SQL仅提供间接解决方案:动态查询。首先,您必须从Status_ID中找到所有不同的值,然后下一步是构建最终查询:
DECLARE @SQLStatement NVARCHAR(4000)
,@PivotValues NVARCHAR(4000);
SET @PivotValues = '';
SELECT @PivotValues = @PivotValues + ',' + QUOTENAME(src.Status_ID)
FROM
(
SELECT DISTINCT Status_ID
FROM Table
) src;
SET @PivotValues = SUBSTRING(@PivotValues,2,4000);
SELECT @SQLStatement =
'SELECT pvt.*
FROM
(
SELECT Date, Id, Status_ID, Status_Time
FROM Table
) src
PIVOT ( SUM(src.Status_Time) FOR src.Status_ID IN ('+@PivotValues+') ) pvt';
EXECUTE sp_executesql @SQLStatement;