[英]Add more columns for each value of another column?
I have this kind of table : 我有这种桌子:
Name Date Value
-----------------------
Test 1/1/2001 10
Test 2/1/2001 17
Test 3/1/2001 52
Foo 5/4/2011 15
Foo 6/4/2011 321
My 15/5/2005 36
My 25/7/2005 75
And I would like to show the results like this : 我想显示这样的结果:
Name Date Value Name Date Value Name Date Value
---------------------------------------------------------------------
Test 1/1/2001 10 Foo 5/4/2011 15 My 15/5/2005 36
Test 2/1/2001 17 Foo 6/4/2011 321 My 25/7/2005 75
Test 3/1/2001 52
I need to show as many columns as what is present in my Name column 我需要显示与“名称”列中显示的列一样多的列
How could I do this in Sql ? 如何在Sql中执行此操作?
In order to get the result that you want, you are going to have to unpivot the columns in your table and apply the pivot function. 为了获得所需的结果,您将必须取消 透视表中的列并应用透视功能。
The unpivot can be done using either the UNPIVOT
function or you can use CROSS APPLY
with VALUES
. 该UNPIVOT就可以利用来完成
UNPIVOT
功能,也可以使用CROSS APPLY
与VALUES
。
UNPIVOT: 志愿人员:
select rn,
col +'_'+cast(dr as varchar(10)) col,
new_values
from
(
select name,
convert(varchar(10), date, 101) date,
cast(value as varchar(10)) value,
dense_rank() over(order by name) dr,
row_number() over(partition by name order by date) rn
from yourtable
) d
unpivot
(
new_values
for col in (name, date, value)
) un;
CROSS APPLY: 交叉申请:
select rn,
col +'_'+cast(dr as varchar(10)) col,
c.value
from
(
select name,
convert(varchar(10), date, 101) date,
cast(value as varchar(10)) value,
dense_rank() over(order by name) dr,
row_number() over(partition by name order by date) rn
from yourtable
) d
cross apply
(
values
('Name', name), ('Date', date), ('Value', Value)
) c (col, value);
See SQL Fiddle with Demo of both versions. 请参见带有两个版本的Demo的SQL Fiddle 。 This gives the result:
结果如下:
| RN | COL | NEW_VALUES |
-----------------------------
| 1 | name_1 | Foo |
| 1 | date_1 | 04/05/2011 |
| 1 | value_1 | 15 |
| 2 | name_1 | Foo |
| 2 | date_1 | 04/06/2011 |
| 2 | value_1 | 321 |
| 1 | name_2 | My |
| 1 | date_2 | 05/15/2005 |
| 1 | value_2 | 36 |
These queries take your existing columns values and converts them to rows. 这些查询采用您现有的列值并将其转换为行。 Once they are in rows, you create the new column names by using the windowing function
dense_rank
. 一旦它们进入行,就可以使用开窗函数
dense_rank
创建新的列名。
Once the data has been converted to rows, you then use the new column names (created with the dense_rank
value) and apply the PIVOT
function. 数据转换为行后,您便可以使用新的列名(使用
dense_rank
值创建)并应用PIVOT
函数。
PIVOT with UNPIVOT: PIVOT与UNPIVOT:
select name_1, date_1, value_1,
name_2, date_2, value_2,
name_3, date_3, value_3
from
(
select rn,
col +'_'+cast(dr as varchar(10)) col,
new_values
from
(
select name,
convert(varchar(10), date, 101) date,
cast(value as varchar(10)) value,
dense_rank() over(order by name) dr,
row_number() over(partition by name order by date) rn
from yourtable
) d
unpivot
(
new_values
for col in (name, date, value)
) un
) src
pivot
(
max(new_values)
for col in (name_1, date_1, value_1,
name_2, date_2, value_2,
name_3, date_3, value_3)
) piv;
See SQL Fiddle with Demo 参见带有演示的SQL Fiddle
PIVOT with CROSS APPLY: 带有交叉的PIVOT应用:
select name_1, date_1, value_1,
name_2, date_2, value_2,
name_3, date_3, value_3
from
(
select rn,
col +'_'+cast(dr as varchar(10)) col,
c.value
from
(
select name,
convert(varchar(10), date, 101) date,
cast(value as varchar(10)) value,
dense_rank() over(order by name) dr,
row_number() over(partition by name order by date) rn
from yourtable
) d
cross apply
(
values
('Name', name), ('Date', date), ('Value', Value)
) c (col, value)
) src
pivot
(
max(value)
for col in (name_1, date_1, value_1,
name_2, date_2, value_2,
name_3, date_3, value_3)
) piv;
See SQL Fiddle with Demo . 请参阅带有演示的SQL Fiddle 。
Dyanmic PIVOT: 动态PIVOT:
The above versions will work great if you have a limited or known number of columns, if not, then you will need to use dynamic SQL: 如果您的列数有限或已知,则上述版本将非常有用,否则,您将需要使用动态SQL:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(col +'_'+cast(dr as varchar(10)))
from
(
select dense_rank() over(order by name) dr
from yourtable
) t
cross apply
(
values(1, 'Name'), (2, 'Date'), (3, 'Value')
) c (sort, col)
group by col, dr, sort
order by dr, sort
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT ' + @cols + '
from
(
select rn,
col +''_''+cast(dr as varchar(10)) col,
c.value
from
(
select name,
convert(varchar(10), date, 101) date,
cast(value as varchar(10)) value,
dense_rank() over(order by name) dr,
row_number() over(partition by name order by date) rn
from yourtable
) d
cross apply
(
values
(''Name'', name), (''Date'', date), (''Value'', Value)
) c (col, value)
) x
pivot
(
max(value)
for col in (' + @cols + ')
) p'
execute(@query)
See SQL Fiddle with Demo . 请参阅带有演示的SQL Fiddle 。
The result for each of the queries is: 每个查询的结果是:
| NAME_1 | DATE_1 | VALUE_1 | NAME_2 | DATE_2 | VALUE_2 | NAME_3 | DATE_3 | VALUE_3 |
-------------------------------------------------------------------------------------------------
| Foo | 04/05/2011 | 15 | My | 05/15/2005 | 36 | Test | 01/01/2001 | 10 |
| Foo | 04/06/2011 | 321 | My | 07/25/2005 | 75 | Test | 01/02/2001 | 17 |
| (null) | (null) | (null) | (null) | (null) | (null) | Test | 01/03/2001 | 52 |
By hand or with a program. 通过手工或程序。 Most people are accustomed to showing output in a linear fashion (the default).
大多数人习惯于以线性方式(默认)显示输出。 If someone is asking you to do this, you can tell them that's not how the application works.
如果有人要您这样做,您可以告诉他们这不是应用程序的工作方式。 You can export the result set to csv and then import that into something like Excel and reformat it by hand or use a serverside language like ASP.net or PHP to format the results into a table.
您可以将结果集导出到csv,然后将其导入到Excel之类的文件中,然后手工重新格式化,或者使用服务器端语言(如ASP.net或PHP)将结果格式化为表格。
When you're parsing the output you could check the last var Name against the current. 解析输出时,可以对照当前值检查最后一个var Name。 If they're different then add a column.
如果它们不同,则添加一列。 It would still be tricky to script it because they will more than likely come out of the database in order.
编写脚本仍然很棘手,因为它们很可能会按顺序从数据库中出来。 So you would have a sequence like test, test, test, foo, foo which would mean that you need to create a multidimensional array to organize the data to get a column count.
因此,您将拥有一个诸如test,test,test,foo,foo之类的序列,这意味着您需要创建一个多维数组来组织数据以获取列数。 Then setup the table based on that with a counter that counts row names, then data underneath.
然后根据该表设置一个计数器,该计数器先对行名进行计数,然后对行数进行计数。
I'm not sure which apps you're familiar with, so in PHP the output would look something like this from the multidimensional array. 我不确定您熟悉哪些应用程序,因此在PHP中,多维数组的输出看起来像这样。
row [1]['name']=test
row [1][test][1]['date'] = 1/1/2001
This is more of a visual output though. 但是,这更多是视觉输出。 The databases are designed to hold data and return it in an intuitive fashion.
这些数据库旨在保存数据并以直观的方式返回。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.