如何将单列中的值显示为多个并按另一列分组
How to display values in a single column into multiple and group by another column
我在 SQL Server 2012 中有一个数据库 table "table_name1" 使用以下方法创建:
CREATE TABLE table_name1 (
created_date date,
complete_hour int,
col_percent float
);
INSERT INTO table_name1 values
('2017-06-14', 8, 0.3),
('2017-06-14', 9, 1.96),
('2017-06-14', 10, 3.92),
('2017-06-07', 8, 0.17),
('2017-06-07', 9, 2.87),
('2017-06-07', 10, 3.72),
('2017-05-31', 7, 0.14),
('2017-05-31', 8, 0.72),
('2017-05-31', 9, 3.77),
('2017-05-31', 10, 5.8);
我想要做的是得到如下结果:
created_date col1 col2 col3 col4
2017-06-14 BLANK 0.3 1.96 3.92
2017-06-07 BLANK 0.17 2.87 3.72
2017-05-31 0.14 0.72 3.77 5.8
我试过使用 pivot,因为 table_name1 中的行数会不断变化,我想我必须使用动态 sql。所以我尝试使用 Efficiently convert rows to columns in sql server post 的答案,但无法调整它来解决我的问题。我需要考虑 3 列而不是两列,并且还必须按 created_date 分组。
我可以得到一些关于如何执行此操作的建议吗?
编辑:我试图遵循的答案的小修改版本是:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(col_percent)
from table_name1
group by created_date, complete_hour, col_percent
order by complete_hour
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = N'SELECT ' + @cols + N' from
(
select created_date, col_percent
from table_name1
) x
pivot
(
max(created_date)
for col_percent in (' + @cols + N')
) p '
exec sp_executesql @query;
结果为:
0.14 0.72 0.17 0.3 3.77 2.87 1.96 5.8 3.72 3.92
2017-05-31 2017-05-31 2017-06-07 2017-06-14 2017-05-31 2017-06-07 2017-06-14 2017-05-31 2017-06-07 2017-06-14
我知道我在获取所需输出方面做错了,但是当我尝试更改数据透视表中的列名称时,我得到了或其他一些更改,我得到了 "invalid column name" 或 "The incorrect value " 0.14" 在 PIVOT 运算符中提供。"
你可以做一个动态枢轴来得到你想要的。这是一个使用示例中的临时 table 的示例:
CREATE TABLE #table_name1 (
created_date date,
complete_hour int,
col_percent float
);
INSERT INTO #table_name1 values
('2017-06-14', 8, 0.3),
('2017-06-14', 9, 1.96),
('2017-06-14', 10, 3.92),
('2017-06-07', 8, 0.17),
('2017-06-07', 9, 2.87),
('2017-06-07', 10, 3.72),
('2017-05-31', 7, 0.14),
('2017-05-31', 8, 0.72),
('2017-05-31', 9, 3.77),
('2017-05-31', 10, 5.8);
declare @sql nvarchar(max),
@pvtColumns nvarchar(max),
@selectColumns nvarchar(max)
select @pvtColumns = (
select ''+PivotColumns+','
from (
select distinct
'['+convert(Varchar(10), complete_hour)+']' as PivotColumns, complete_hour
from #table_name1
) as b
order by complete_hour
for xml path('')
)
select @pvtColumns = substring(@pvtColumns,1,len(@pvtColumns)-1)
set @sql =
'
select
p.created_date,
'+@pvtColumns+'
from
(
select
created_date,
complete_hour,
col_percent
from #table_name1
)
as main
pivot
(
max(col_percent)
for complete_hour in ('+@pvtColumns+')
) as p
order by
created_date
'
exec sp_Executesql @sql
如果我们一步一个脚印,让我们先尝试不使用动态 sql。
我相信此查询会产生您要查找的结果:
SELECT created_date, [7] AS col1, [8] AS col2, [9] AS col3, [10] AS col4
FROM
(
select created_date, complete_hour, col_percent
from table_name1
) x
pivot
(
max(col_percent)
for complete_hour in ([7],[8],[9],[10])
) p
ORDER BY created_date DESC
输出:
created_date col1 col2 col3 col4
2017-06-14 NULL 0,3 1,96 3,92
2017-06-07 NULL 0,17 2,87 3,72
2017-05-31 0,14 0,72 3,77 5,8
**** 更新:OP 确认结果看起来正确。现在来一些动态 sql 忍者的东西
为了让它更动态一点,以下方法可行:
我们首先声明将保存列和查询的两个变量:
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
接下来,我们确定要从 table 中抓取的列。在我们的例子中,这是 complete_hour
。看到这些很可能会在几天内重复出现,而我们只需要一次,我们 GROUP BY complete_hour
:
SELECT @cols = STUFF((SELECT ',' + QUOTENAME(complete_hour)
from table_name1
group by complete_hour
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
我们现在可以测试变量中的内容:
PRINT @cols
根据提供的测试数据,目前会包含
[7],[8],[9],[10]
在现实生活中,这将是每个不同 complete_hour 值的值。
开始构建查询:
set @query = N'SELECT created_date, ' + @cols + N' from
(
select created_date, complete_hour, col_percent
from table_name1
) x
pivot
(
max(col_percent)
for complete_hour in (' + @cols + N')
) p
ORDER BY created_date DESC
'
正如您想要的 created_date 列,它需要在 SELECT 语句中。我们还需要 complete_hour 的每个值,这是我们存储在@cols 中的值。
我们实际上想要抓取所有内容,所以我们 select 所有三列,然后为每个 complete_hour 旋转 col_percent。
最后,我们按 created_date
排序,最晚的日期排在最前面。
然后我们可以执行:
exec sp_executesql @query;
我在 SQL Server 2012 中有一个数据库 table "table_name1" 使用以下方法创建:
CREATE TABLE table_name1 (
created_date date,
complete_hour int,
col_percent float
);
INSERT INTO table_name1 values
('2017-06-14', 8, 0.3),
('2017-06-14', 9, 1.96),
('2017-06-14', 10, 3.92),
('2017-06-07', 8, 0.17),
('2017-06-07', 9, 2.87),
('2017-06-07', 10, 3.72),
('2017-05-31', 7, 0.14),
('2017-05-31', 8, 0.72),
('2017-05-31', 9, 3.77),
('2017-05-31', 10, 5.8);
我想要做的是得到如下结果:
created_date col1 col2 col3 col4
2017-06-14 BLANK 0.3 1.96 3.92
2017-06-07 BLANK 0.17 2.87 3.72
2017-05-31 0.14 0.72 3.77 5.8
我试过使用 pivot,因为 table_name1 中的行数会不断变化,我想我必须使用动态 sql。所以我尝试使用 Efficiently convert rows to columns in sql server post 的答案,但无法调整它来解决我的问题。我需要考虑 3 列而不是两列,并且还必须按 created_date 分组。
我可以得到一些关于如何执行此操作的建议吗?
编辑:我试图遵循的答案的小修改版本是:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(col_percent)
from table_name1
group by created_date, complete_hour, col_percent
order by complete_hour
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = N'SELECT ' + @cols + N' from
(
select created_date, col_percent
from table_name1
) x
pivot
(
max(created_date)
for col_percent in (' + @cols + N')
) p '
exec sp_executesql @query;
结果为:
0.14 0.72 0.17 0.3 3.77 2.87 1.96 5.8 3.72 3.92
2017-05-31 2017-05-31 2017-06-07 2017-06-14 2017-05-31 2017-06-07 2017-06-14 2017-05-31 2017-06-07 2017-06-14
我知道我在获取所需输出方面做错了,但是当我尝试更改数据透视表中的列名称时,我得到了或其他一些更改,我得到了 "invalid column name" 或 "The incorrect value " 0.14" 在 PIVOT 运算符中提供。"
你可以做一个动态枢轴来得到你想要的。这是一个使用示例中的临时 table 的示例:
CREATE TABLE #table_name1 (
created_date date,
complete_hour int,
col_percent float
);
INSERT INTO #table_name1 values
('2017-06-14', 8, 0.3),
('2017-06-14', 9, 1.96),
('2017-06-14', 10, 3.92),
('2017-06-07', 8, 0.17),
('2017-06-07', 9, 2.87),
('2017-06-07', 10, 3.72),
('2017-05-31', 7, 0.14),
('2017-05-31', 8, 0.72),
('2017-05-31', 9, 3.77),
('2017-05-31', 10, 5.8);
declare @sql nvarchar(max),
@pvtColumns nvarchar(max),
@selectColumns nvarchar(max)
select @pvtColumns = (
select ''+PivotColumns+','
from (
select distinct
'['+convert(Varchar(10), complete_hour)+']' as PivotColumns, complete_hour
from #table_name1
) as b
order by complete_hour
for xml path('')
)
select @pvtColumns = substring(@pvtColumns,1,len(@pvtColumns)-1)
set @sql =
'
select
p.created_date,
'+@pvtColumns+'
from
(
select
created_date,
complete_hour,
col_percent
from #table_name1
)
as main
pivot
(
max(col_percent)
for complete_hour in ('+@pvtColumns+')
) as p
order by
created_date
'
exec sp_Executesql @sql
如果我们一步一个脚印,让我们先尝试不使用动态 sql。
我相信此查询会产生您要查找的结果:
SELECT created_date, [7] AS col1, [8] AS col2, [9] AS col3, [10] AS col4
FROM
(
select created_date, complete_hour, col_percent
from table_name1
) x
pivot
(
max(col_percent)
for complete_hour in ([7],[8],[9],[10])
) p
ORDER BY created_date DESC
输出:
created_date col1 col2 col3 col4
2017-06-14 NULL 0,3 1,96 3,92
2017-06-07 NULL 0,17 2,87 3,72
2017-05-31 0,14 0,72 3,77 5,8
**** 更新:OP 确认结果看起来正确。现在来一些动态 sql 忍者的东西
为了让它更动态一点,以下方法可行:
我们首先声明将保存列和查询的两个变量:
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
接下来,我们确定要从 table 中抓取的列。在我们的例子中,这是 complete_hour
。看到这些很可能会在几天内重复出现,而我们只需要一次,我们 GROUP BY complete_hour
:
SELECT @cols = STUFF((SELECT ',' + QUOTENAME(complete_hour)
from table_name1
group by complete_hour
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
我们现在可以测试变量中的内容:
PRINT @cols
根据提供的测试数据,目前会包含
[7],[8],[9],[10]
在现实生活中,这将是每个不同 complete_hour 值的值。
开始构建查询:
set @query = N'SELECT created_date, ' + @cols + N' from
(
select created_date, complete_hour, col_percent
from table_name1
) x
pivot
(
max(col_percent)
for complete_hour in (' + @cols + N')
) p
ORDER BY created_date DESC
'
正如您想要的 created_date 列,它需要在 SELECT 语句中。我们还需要 complete_hour 的每个值,这是我们存储在@cols 中的值。
我们实际上想要抓取所有内容,所以我们 select 所有三列,然后为每个 complete_hour 旋转 col_percent。
最后,我们按 created_date
排序,最晚的日期排在最前面。
然后我们可以执行:
exec sp_executesql @query;