【问题标题】:How to flatten a table using SQL Server?如何使用 SQL Server 展平表?
【发布时间】:2014-04-04 12:07:33
【问题描述】:

我正在使用 SQL Server 2012。对于一个项目,我想展平一个表格,但我需要一些帮助。我的桌子。

| ApplicationName   | Name        | Value                   | CreatedOn
| Contoso           | Description | An example website      | 04-04-2014
| Contoso           | Description | Nothing                 | 02-04-2014
| Contoso           | Keywords    | Contoso, About, Company | 04-04-2014
| Contoso           | Keywords    | Contoso, Company        | 02-04-2014

我想通过应用程序名称从名称中获取最后修改记录。我想要的结果。

| ApplicationName    | Description        | Keywords
| Contoso            | An example website | Contoso, About, Company

我不喜欢临时表。谁知道怎么做?

非常感谢。

乔迪

【问题讨论】:

标签: sql sql-server sql-server-2008 sql-server-2012 ssms


【解决方案1】:

这里是更完整的解决方案:

declare @collist nvarchar(max)
SET @collist = stuff((select distinct ',' + QUOTENAME(name) 
            FROM table -- your table here
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

declare @q nvarchar(max)
set @q = '
select * 
from (
    select ApplicationName, name, Value
        from (
        select *, row_number() over (partition by ApplicationName, name order by CreatedOn desc) as rn
        from table -- your table here
        where appname = ''contoso''
    ) as x
    where rn = 1 
) as source
pivot (
    max(Value)
    for name in (' + @collist + ')
) as pvt
'

exec (@q)

【讨论】:

    【解决方案2】:

    您将不得不使用数据透视表来执行此操作。如果 Name 的值的数量未知,您还需要使用一些动态 sql。您可能会发现对此有用的 3 篇文章是:

    Pivot Tables

    SQL Server Cursors

    Dynamic Sql

    编辑:

    这是一个可能的例子

    --Get the list of names
    
    DECLARE @values varchar(MAX);
    
    SELECT @values = COALESCE(@values, '') + '[' + Name + '],' FROM table;
    
    SET @values = SUBSTRING(@values, 1, LEN(@values) - 1);
    
    --build the sql string using these names
    
    DECLARE @sql varchar(MAX) = 'SELECT applicationName, ' + @values + 'FROM (';
    SET @sql = @sql + 'SELECT applicationName, Name, Value FROM tableName WHERE CreatedOn = (SELECT MAX(CreatedOn) FROM tableName WHERE ApplicationName = @appName) AND applicationName = @appName) AS toPivot';
    
    SET @sql = @sql + 'PIVOT (';
    
    SET @sql = @sql + 'MAX(Value) FOR Name IN (' + @values + ')) As p';
    
    --run sql
    
    DECLARE @ParamDefinition varchar(MAX) = '@appName varchar(MAX)';
    
    DECLARE @selectedApp varchar(MAX) = 'put the app you want here';
    
    EXECUTE sp_executesql @sql, @ParamDefinition, @appName = @selectedApp;
    

    请注意,我假设 CreatedOn 值对于您对应用程序感兴趣的每个名称都是相同的。

    再次编辑:

    我下面的解决方案有一个非常好的技巧来计算每个条目的最近日期(如果它们不同)。

    免责声明,由于我是在头顶的答案窗口中执行此操作的,因此可能不是 100% 正确,但它应该让您非常接近。

    【讨论】:

    • 感谢您的链接。我尝试了很多这样的东西,但我无法修复它。
    • 我刚刚添加了一个例子
    【解决方案3】:

    这是执行此操作的基本方法。用您的表替换临时表。

    DECLARE @tmp TABLE (
       ApplicationName VARCHAR(25),
       [Name] VARCHAR(25),
       [Value] VARCHAR(100),
       CreatedOn Date )
    INSERT INTO @tmp VALUES
       ('Contoso','Description','An example website','04-04-2014'),
       ('Contoso','Description','Nothing','02-04-2014'),
       ('Contoso','Keywords','Contoso, About, Company','04-04-2014'),
       ('Contoso','Keywords','Contoso, Company','02-04-2014')
    
    SELECT a.ApplicationName,
      a.[Value] AS [Description],
      d.Value AS [Keywords]
    FROM @tmp AS a
      -- filter the rows by max date
    INNER JOIN (SELECT c.applicationName, MAX(c.CreatedOn) AS mCreated 
            FROM @tmp AS c 
            GROUP BY c.applicationName
            ) AS b ON a.ApplicationName = b.ApplicationName AND a.CreatedOn = b.mCreated 
    AND a.Name = 'Description'
       -- go back and get the matching key words
    INNER JOIN @tmp AS d ON a.ApplicationName = d.ApplicationName AND d.Name = 'Keywords' AND  
     d.CreatedOn = a.CreatedOn
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-19
      • 2016-10-10
      • 1970-01-01
      • 2018-04-09
      • 1970-01-01
      • 2010-12-28
      • 2019-06-05
      • 1970-01-01
      相关资源
      最近更新 更多