Question

I'm using SQL Server 2012. For a project I want to flatten a table, but i need some help. My table.

| 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

I want to get the last modification record from a Name by Application Name. The result i want.

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

I don't like temp tables. Who knows how to do this?

Thanks a lot.

Jordy

Was it helpful?

Solution

Here's the more complete solution:

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)

OTHER TIPS

You are going to have to use a pivot table to do this. If the number of values for Name are unknown, you will also need to use some dynamic sql. 3 Articles you will probably find useful for this are:

Pivot Tables

SQL Server Cursors

Dynamic Sql

EDIT:

Here is a possible example

--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;

Note that I am assuming that the CreatedOn value will be the same for every Name you are interested in for an application.

Edit again:

The solution below mine has a really nice trick for working out the most recent date for each entry if they are different.

DISCLAIMER, since I did this in the answer window off the top of my head, it may not be 100% right, but it should get you pretty close.

Here is a basic way to do this. Replace the temp table with your table.

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top