简体   繁体   English

为另一列的每个值添加更多列?

[英]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 APPLYVALUES

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. 请参见带有两个版本的DemoSQL 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.

相关问题 SQLite基于另一个列值添加列 - Sqlite add column based on another columns value 从一列中只为另一个列中的每个值选择一个值,以及对应的其他列值 - Select only one value from a column for each value in another column, together with corresponding other columns value SQL 根据另一列的值添加列 - SQL Add columns based on value from another column 如何基于SQL中的另一个列值将列添加到表 - How to add column to a table based on another columns value in SQL 如何将两列的值作为值添加到 SQL 中的另一列 - How to add values of two columns as a value to another column in SQL 查询Hive QL另一列中与每个值关联的最短字符串值的更有效方法 - More efficient way to query shortest string value associated with each value in another column in Hive QL 如果两个现有列匹配,则SQL查询添加新列,并从另一列添加值 - SQL query add new column if two existing columns matches and add value from another column 如何将更多行添加到表/数据框中,并将日期增加到某个日期以获取另一列的所有值 - How to add more rows to a table/dataframe with increasing dates to a certain date for all value of another column 如何像其他列的sum()一样添加列 - How to add a column like a sum() of another columns SQL计算列中每个不同的值,并从ID匹配的另一个表中添加名称 - SQL count each distinct value in column and add name from another table where the ID matches
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM