sql query including month columns? - sql

I was wondering if I could get some ideas or direction on a sql query that would output column months. Here is my current query..
select A.assetid, A.Acquisition_Cost, B.modepreciaterate from FA00100 A
inner join FA00200 B on A.assetindex = B.assetindex
where MoDepreciateRate != '0'
I would like to add more columns that look as such:
select assetid, acquisition_cost, perdeprrate, Dec_2012, Jan_2013, Feb_2013....
where Dec_2012 = (acquisition_cost - MoDepreciateRate*(# of months))
and Jan_2013 = (acquisition_cost - MoDepreciateRate*(# of months))
where # of months can be changed.
Any help would be really appreciated. Thank you!
Here is an example of what I would like the output to be with '# of months' = 4
assetid SHRTNAME Acquisition_Cost perdeprrate Dec_2012 Jan_2013 Feb_2013 Mar_2013
CS-013 GEH INTEG 17490.14 485.83 17004.31 16518.48 16032.65 15546.82
CS-014 WEB BRD 14560 404.4507 14155.5493 13751.0986 13346.6479 12942.1972

Try This:
--setup
create table #fa00100 (assetId int, assetindex int, acquisitionCost int, dateAcquired date)
create table #fa00200 (assetIndex int, moDepreciateRate int, fullyDeprFlag nchar(1), fullyDeprFlagBit bit)
insert #fa00100
select 1, 1, 100, '2012-01-09'
union select 2, 2, 500, '2012-05-09'
insert #fa00200
select 1, 10, 'N', 0
union select 2, 15, 'Y', 1
.
--solution
create table #dates (d date not null primary key clustered)
declare #sql nvarchar(max)
, #pivotCols nvarchar(max)
, #thisMonth date
, #noMonths int = 4
set #thisMonth = cast(1 + GETUTCDATE() - DAY(getutcdate()) as date)
select #thisMonth
while #noMonths > 0
begin
insert #dates select DATEADD(month,#noMonths,#thisMonth)
set #noMonths = #noMonths - 1
end
select #sql = ISNULL(#sql + NCHAR(10) + ',', '')
--+ ' A.acquisitionCost - (B.moDepreciateRate * DATEDIFF(month,dateAcquired,''' + convert(nvarchar(8), d, 112) + ''')) ' --Original Line
+ ' case when A.acquisitionCost - (B.moDepreciateRate * DATEDIFF(month,dateAcquired,''' + convert(nvarchar(8), d, 112) + ''')) <= 0 then 0 else A.acquisitionCost - (B.moDepreciateRate * DATEDIFF(month,dateAcquired,''' + convert(nvarchar(8), d, 112) + ''')) end ' --new version
+ quotename(DATENAME(month, d) + '_' + right(cast(10000 + YEAR(d) as nvarchar(5)),4))
from #dates
set #sql = 'select A.assetid
, A.acquisitionCost
, B.moDepreciateRate
,' + #sql + '
from #fa00100 A
inner join #fa00200 B
on A.assetindex = B.assetindex
where B.fullyDeprFlag = ''N''
and B.fullyDeprFlagBit = 0
'
--nb: B.fullyDeprFlag = ''N'' has double quotes to avoid the quotes from terminating the string
--I've also included fullyDeprFlagBit to show how the SQL would look if you had a bit column - that will perform much better and will save space over using a character column
print #sql
exec(#sql)
drop table #dates
.
--remove temp tables from setup
drop table #fa00100
drop table #fa00200

Related

Combining 2 temp queries into 1

I have tried combining 2 queries into 1. However, I ran into some problems:
exec(#sql + #sql2 + #sql3)
exec(#sql4 + #sql5 + #sql6)
Executing the above, I have the following results:
However, since I would like to combine the 2 queries into 1 using date, I wrote a few more lines as followed:
--Join the 2 queries together for comparison
select a.stime as Date,
a.bid as BidA,
a.ask as AskA,
b.bid as BidB,
b.ask as AskB,
ABS(ISNULL(a.bid, 0) - ISNULL(b.bid, 0)) as BidDiff,
ABS(ISNULL(a.ask, 0) - ISNULL(b.ask, 0)) as AskDiff
from (exec(#sql + #sql2 + #sql3)) a left outer join (exec(#sql4 + #sql5 + #sql6)) b where a.stime = b.stime
Order by date DESC;
However, I kept getting an incorrect syntax error nearby exec.
Create 2 table variables (not sure what your data types are):
DECLARE #tableA AS TABLE([stime] AS datetime, [Bid] AS blah, [Ask] AS blah)
DECLARE #tableB AS TABLE([stime] AS datetime, [Bid] AS blah, [Ask] AS blah)
INSERT INTO #tableA
EXEC (#sql + #sql2 + #sql3)
INSERT INTO #tableB
EXEC (#sql4 + #sql5 + #sql6)
SELECT
[A].[stime] AS [Date]
, [A].[Bid] AS [BidA]
, [A].[Ask] AS [AskA]
, [B].[Bid] AS [BidB]
, [B].[Ask] AS [AskB]
, ABS(ISNULL([A].[Bid], 0) - ISNULL([B].[Bid], 0)) AS [BidDiff]
, ABS(ISNULL([A].[Ask], 0) - ISNULL([B].[Ask], 0)) AS [AskDiff]
FROM #TableA AS [A]
LEFT JOIN #TableB AS [B]
ON [A].[stime] = [B].[stime]
ORDER BY [A].[stime] DESC

Convert Row to Column based on data in SQL

The below image is my table
The below excel is the design for output.
My table contains 12 columns for each month and an year column. An item, there it can be available in multiple years and data for each month.
year- itemcode- jan- feb
2014- pqr- 12- 11
2015- pqr- 4- 8
I need to generated the below output. For an item available for multiple years
output needs to list in the following manner.
ItemCode- Jan14- Feb14- Mar14-... Dec14- Jan15- Feb15-... Dec15
pqr- 12- 11- 4- 8-
How can I able to achieve this.
I tried different methods after googling. But I am not able to get proper input for solving this.
At present I am trying some solutions found in SO. It will be very helpful someone can give some inputs. Thanks in advance.
You'll need to use dymanic SQL...
Basically assuming a table called #tbl (with a little bit of sample data - ive only done 3 months but extend to 12!)
CREATE TABLE #tbl ([ItemCode] NVARCHAR(20), [Year] INT, Jan INT, Feb INT, Mar INT)
INSERT #tbl ( ItemCode, Year, Jan, Feb, Mar )
VALUES ( 'pqr', 2014, 12, 11, 7 ), ( 'pqr', 2015, 4, 8, 0 ),
( 'xyz', 2015, 7, 1, 0 ), ( 'abc', 2013, 63, 23, 12 ), ( 'abc', 2015, 63, 23, 12 )
we want to generate a query that looks like
SELECT tbase.ItemCode
, ISNULL(t13.Jan,0) AS 'Jan-13', ISNULL(t13.Feb,0) AS 'Feb-13', ISNULL(t13.Mar,0) AS 'Mar-13'
, ISNULL(t14.Jan,0) AS 'Jan-14', ISNULL(t14.Feb,0) AS 'Feb-14', ISNULL(t14.Mar,0) AS 'Mar-14'
, ISNULL(t15.Jan,0) AS 'Jan-15', ISNULL(t15.Feb,0) AS 'Feb-15', ISNULL(t15.Mar,0) AS 'Mar-15'
FROM
(SELECT DISTINCT(ItemCode) AS ItemCode FROM #tbl) AS tbase
LEFT JOIN (SELECT * FROM #tbl AS t13 WHERE YEAR = 2013) AS t13 ON t13.ItemCode = tbase.ItemCode
LEFT JOIN (SELECT * FROM #tbl AS t14 WHERE YEAR = 2014) AS t14 ON t14.ItemCode = tbase.ItemCode
LEFT JOIN (SELECT * FROM #tbl AS t15 WHERE YEAR = 2015) AS t15 ON t15.ItemCode = tbase.ItemCode
And results like:
ItemCode Jan-13 Feb-13 Mar-13 Jan-14 Feb-14 Mar-14 Jan-15 Feb-15 Mar-15
abc 63 23 12 0 0 0 63 23 12
pqr 0 0 0 12 11 7 4 8 0
xyz 0 0 0 0 0 0 7 1 0
As you can see from the query - the 2 things to buld up are the lines , ISNULL(t13.Jan,0)... and LEFT JOIN (SELECT ...
we can do this by declaring 2 NVARCHAR(MAX) variables (one for the select, one for the from) and building them up inside a while loop while iterating through the available years.
ie something like...
DECLARE #select NVARCHAR(MAX);
DECLARE #from NVARCHAR(MAX);
DECLARE #years TABLE(yr INT);
DECLARE #year INT;
DECLARE #yearName NVARCHAR(2)
INSERT #years
SELECT DISTINCT [Year] FROM #tbl
SELECT #year = MIN(yr) FROM #years
SELECT #yearName = RIGHT(CAST(#year AS NVARCHAR(4)),2)
SELECT #select = 'SELECT tbase.ItemCode'
SELECT #from = 'FROM (SELECT DISTINCT(ItemCode) AS ItemCode FROM #tbl) AS tbase '
WHILE EXISTS (SELECT NULL FROM #years WHERE yr = #year)
BEGIN
SELECT #yearName = RIGHT(CAST(#year AS NVARCHAR(4)),2)
SELECT #select = #select + CHAR(13) + CHAR(10)
+ ', ISNULL(t' + #yearName + '.Jan,0) AS [Jan-' + #yearName + '],'
+ ' ISNULL(t' + #yearName + '.Feb,0) AS [Feb-' + #yearName + '],'-- +9 more
+ ' ISNULL(t' + #yearName + '.Mar,0) AS [Mar-' + #yearName + '] '
SELECT #from = #from + CHAR(13) + CHAR(10)
+ 'LEFT JOIN (SELECT * FROM #tbl AS t' + #yearName
+ ' WHERE [Year] = ' + CAST(#year AS NVARCHAR(4)) + ') AS t' + #yearName
+ ' ON t' + #yearName + '.ItemCode = tbase.ItemCode '
SELECT #year = #year + 1
END
DECLARE #sql NVARCHAR(MAX)
SELECT #sql = #select + CHAR(13) + CHAR(10) + #from
EXEC (#sql)
All you need to do is extend this to the full 12 months and you're done!
NB - I've assumed that there is at least 1 entry for every year. If you have a gap where there is a year in the middle of your range with no entries whatsoever you'd need to do a minor modification to the WHILE loop - ie WHILE #year <= (SELECT MAX(Year) FROM #years)
Suppose you have the following table :
select 'AA' as ItemCode,2014 as year, 23 as Jan, 55 as Feb, 55 as Mar,565 as Apr,656 as May,
343 as Jun,54 as Jul,23 as Aug,66 as Sep,645 as Oct,32 as Nov,66 as Dec
into dbo.test ;
insert into dbo.test select 'AA',2015,554,456,3,54,756,98,2,765,24,876,34,66
union select 'BB',2014,45,56,3,54,756,98,2,765,24,876,34,66
union select 'BB',2015,45,56,3,54,756,98,2,765,24,876,34,66;
With dynamic sql, do
declare #sql nvarchar(1000);
declare #sql2 nvarchar(1000);
declare #year int;
declare #first_year int;
declare c cursor for select distinct year from dbo.test;
open c;
FETCH NEXT FROM c into #year
if ##FETCH_STATUS = 0
begin
select #sql='select test'+convert(varchar,#year)+'.ItemCode';
select #sql = #sql+',test'+CONVERT(varchar,#year)+'.Jan as Jan'+CONVERT(varchar,#year)+',test'
+CONVERT(varchar,#year)+'.Feb as Feb'+CONVERT(varchar,#year)+',test'
+CONVERT(varchar,#year)+'.Mar as Mar'+CONVERT(varchar,#year);
select #sql2='test test'+CONVERT(varchar,#year);
select #first_year=#year;
end;
FETCH NEXT FROM c into #year
WHILE ##FETCH_STATUS = 0
begin
select #sql = #sql+',test'+CONVERT(varchar,#year)+'.Jan as Jan'+CONVERT(varchar,#year)+',test'
+CONVERT(varchar,#year)+'.Feb as Feb'+CONVERT(varchar,#year)+',test'
+CONVERT(varchar,#year)+'.Mar as Mar'+CONVERT(varchar,#year);
select #sql2=#sql2+' inner join test test'+CONVERT(varchar,#year)+' on test'+CONVERT(varchar,#year)+'.ItemCode=test'+CONVERT(varchar,#first_year)+'.ItemCode and test'+CONVERT(varchar,#year)+'.year='+CONVERT(varchar,#year);
FETCH NEXT FROM c into #year
end;
close c;
deallocate c;
select #sql=#sql+' FROM '+#sql2 + ' AND test'+convert(varchar,#first_year)+'.year='+CONVERT(varchar,#year);
print #sql
EXECUTE sp_executesql #sql;
Or, with standard SQL, something like this
select test2014.ItemCode,test2014.Jan as Jan2014,test2014.Feb as Feb2014,test2015.Jan as Jan2015,test2015.Feb as Feb2015
from test test2014 inner join test test2015 on test2014.ItemCode=test2015.ItemCode
where test2014.year=2014 and test2015.year=2015;

2005 SSRS/SQL Server PIVOT results need reversing

Preamble: I've read through the three questions/answers here,here, and here, with big ups to #cade-roux. This all stemmed from trying to use the following data in a 2005 SSRS matrix that, I believe, doesn't work because I want to show a member having to take a test multiple times, and SSRS seems to require the aggregate where I want to show all dates.
I get the following results in my table, which seems to be showing all the data correctly:
How do I change the code below to show a) the "tests" at the top of each column with b) if it's called for, the multiple dates that test was taken?
Here's the code I have to produce the table, above. Much of it is commented out as I was just trying to get the pivot to work, but you may notice I am also trying to specify which test column comes first.
CREATE TABLE #tmp ( ---THIS WORKS BUT TESTS ARE VERTICAL
[TEST] [varchar](30) NOT NULL,
[ED] [datetime] NOT NULL
)
--WHERE THE TEST AND ED COME FROM
INSERT #TMP
SELECT DISTINCT
-- N.FULL_NAME
-- , CONVERT(VARCHAR(30), AM.CREATEDATE, 101) AS ACCOUNT_CLAIMED
-- , N.EMAIL
-- , NULL AS 'BAD EMAIL'
-- , CONVERT(VARCHAR(30), AC.EFFECTIVE_DATE, 101) AS EFFECTIVE_DATE
AC.PRODUCT_CODE AS TEST
, CONVERT(VARCHAR(30), AC.EFFECTIVE_DATE, 101) AS ED
-- , CASE
-- WHEN AC.PRODUCT_CODE = 'NewMem_Test' THEN '9'
-- WHEN AC.PRODUCT_CODE = 'NM_Course1' THEN '1'
-- WHEN AC.PRODUCT_CODE = 'NMEP_Course1' THEN '2'
-- WHEN AC.PRODUCT_CODE = 'NMEP_Course2' THEN '3'
-- WHEN AC.PRODUCT_CODE = 'NMEP_Course3' THEN '4'
-- WHEN AC.PRODUCT_CODE = 'NMEP_Course4' THEN '5'
-- WHEN AC.PRODUCT_CODE = 'NMEP_Course5' THEN '6'
-- WHEN AC.PRODUCT_CODE = 'NMEP_Course6' THEN '7'
-- WHEN AC.PRODUCT_CODE = 'NMEP_Course7' THEN '8'
-- END AS 'COLUMN_ORDER'
FROM NAME N
JOIN USERMAIN UM
ON N.ID = UM.CONTACTMASTER
JOIN formTransLog TL
ON UM.USERID = TL.USERNAME
JOIN anet_Users AU
ON UM.USERID = AU.USERNAME
JOIN anet_Membership AM
ON AU.USERID = AM.USERID
JOIN ACTIVITY AC
ON N.ID = AC.ID
AND AC.ACTIVITY_TYPE = 'COURSE'
AND AC.PRODUCT_CODE LIKE 'N%'
--ORDER BY 1, 7
DECLARE #sql AS varchar(max)
DECLARE #pivot_list AS varchar(max) -- Leave NULL for COALESCE technique
DECLARE #select_list AS varchar(max) -- Leave NULL for COALESCE technique
SELECT #pivot_list = COALESCE(#pivot_list + ', ', '') + '[' + CONVERT(varchar, PIVOT_CODE) + ']'
,#select_list = COALESCE(#select_list + ', ', '') + '[' + CONVERT(varchar, PIVOT_CODE) + '] AS [col_' + CONVERT(varchar, PIVOT_CODE) + ']'
FROM (
SELECT DISTINCT PIVOT_CODE
FROM (
SELECT TEST, ED, ROW_NUMBER() OVER (PARTITION BY TEST ORDER BY ED) AS PIVOT_CODE
FROM #tmp
) AS rows
) AS PIVOT_CODES
SET #sql = '
;WITH p AS (
SELECT TEST, ED, ROW_NUMBER() OVER (PARTITION BY TEST ORDER BY ED) AS PIVOT_CODE
FROM #tmp
)
SELECT TEST, ' + #select_list + '
FROM p
PIVOT (
MIN(ED)
FOR PIVOT_CODE IN (
' + #pivot_list + '
)
) AS pvt
'
PRINT #sql
EXEC (#sql)
EDIT:
The goal is to have the report in SSRS look like this:
I was able to produce the results you were looking for by adding in a number (RowNum) to the query underneath the PIVOT operator. It doesn't have to be in the final query (though you might want it for client-side sorting), but by having it in the underlying layer the PIVOT operation treats that number like a member of a GROUP BY clause.
Please look through my sample SQL below and let me know if this matches your criteria.
CREATE TABLE #TMP
(
Name VARCHAR(10),
Test VARCHAR(20),
EffectiveDate DATETIME
)
INSERT INTO #TMP (Name, Test, EffectiveDate)
SELECT 'Jane', 'NM_Course1', '01/17/2014' UNION
SELECT 'Jane', 'NMEP_Course1', '12/19/2013' UNION
SELECT 'Jane', 'NMEP_Course1', '12/20/2013' UNION
SELECT 'Jane', 'NMEP_Course2', '12/19/2013' UNION
SELECT 'Jane', 'NMEP_Course2', '12/22/2013' UNION
SELECT 'Jane', 'NMEP_Course2', '01/05/2014' UNION
SELECT 'John', 'NM_Course1', '01/17/2014' UNION
SELECT 'John', 'NMEP_Course1', '01/11/2014'
DECLARE #sql AS varchar(max)
DECLARE #pivot_list AS varchar(max) -- Leave NULL for COALESCE technique
DECLARE #select_list AS varchar(max) -- Leave NULL for COALESCE technique
SELECT #pivot_list = COALESCE(#pivot_list + ', ', '') + '[' + CONVERT(varchar, PIVOT_CODE) + ']'
,#select_list = COALESCE(#select_list + ', ', '') + '[' + CONVERT(varchar, PIVOT_CODE) + '] AS [col_' + CONVERT(varchar, PIVOT_CODE) + ']'
FROM (
SELECT DISTINCT PIVOT_CODE
FROM (
SELECT TEST AS PIVOT_CODE
FROM #tmp
) AS rows
) AS PIVOT_CODES
SET #sql = '
SELECT Name, ' + #select_list + '
FROM
(
SELECT b.Name, RowNum, b.EffectiveDate, b.TEST AS PIVOT_CODE
FROM
(
SELECT Name, Test, EffectiveDate, ROW_NUMBER() OVER (PARTITION BY NAME, TEST ORDER BY EffectiveDate) RowNum
FROM #Tmp
) b
) p
PIVOT (
MIN(EffectiveDate)
FOR PIVOT_CODE IN (
' + #pivot_list + '
)
) AS pvt
ORDER BY Name, RowNum
'
PRINT #sql
EXEC (#sql)
DROP TABLE #TMP

change the column name while selecting from dyanamic table

Hi I have attendence query which will generate the attendence report with using PIVOT function
Here's the procedure :
declare #in_date DATETIME
/*Select all the stagign entries related to promotion id and investment type id */
/* also only those staging daat related interface status tracking*/
-- Getting all distinct dates into a temporary table #Dates
SELECT a.date as full_date_of_attendence INTO #Dates
FROM dbo.getFullmonth(#in_date) a
ORDER BY a.date
-- The number of days will be dynamic. So building
-- a comma seperated value string from the dates in #Dates
SELECT #cols = COALESCE(#cols + ',[' + CONVERT(varchar, full_date_of_attendence, 106)
+ ']','[' + CONVERT(varchar, full_date_of_attendence, 106) + ']')
FROM #Dates
ORDER BY full_date_of_attendence
--select #cols
---- Building the query with dynamic dates
SET #qry =
'SELECT * FROM
(SELECT admission_id, attendence_status , date_of_attendence
FROM dbo.tblattendence)emp
PIVOT (MAX(attendence_status) FOR date_of_attendence IN (' + #cols + ')) AS stat'
-- Executing the query
EXEC(#qry)
-- Dropping temporary tables
DROP TABLE #Dates
here is the output of the above query::
admission_id 01 May 2013 02 May 2013 03 May 2013
2 NULL 1 0
3 NULL 1 1
4 NULL 0 0
5 NULL 0 1
Here I want to change the names of the columns as 01,02,03......
and I want the values 1 as 'P' and 0 as 'A'
can anyone would help me to achieve this ??
I would suggest the following changes to your code. If you want a list of the days (1, 2, 3, etc), then you can use the DAY function.
Typically when I get a list of columns dynamically, my preference is using STUFF and FOR XML PATH, I would alter that code to the following:
select #colsPiv = STUFF((SELECT ',' + QUOTENAME(cast(day(full_date_of_attendence) as varchar(2)))
from #Dates
GROUP BY full_date_of_attendence
ORDER BY full_date_of_attendence
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
Then if you want to replace the 0 with an A and a 1 with a P, you will want to create a query to get a list of columns to replace the values:
select #colsSel = STUFF((SELECT ', case when ' + QUOTENAME(cast(day(full_date_of_attendence) as varchar(2)))+'= 1 then ''P'' else ''A'' end as '+QUOTENAME(cast(day(full_date_of_attendence) as varchar(2)))
from #Dates
GROUP BY full_date_of_attendence
ORDER BY full_date_of_attendence
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
Basically, this is creating a select list similar to this:
select case when [1] = 1 then 'P' else 'A' end as [1], ...
Then your final query will be:
SET #qry =
'SELECT admission_id, '+#colsSel +'
FROM
(
SELECT admission_id,
attendence_status ,
day(date_of_attendence) date_of_attendence
FROM dbo.tblattendence
)emp
PIVOT
(
MAX(attendence_status)
FOR date_of_attendence IN (' + #colsPiv + ')
) AS stat'
See SQL Fiddle with Demo
Let's change just the two things you wanted to, i.e.
CONVERT(CHAR(2), full_date_of_attendence, 106) -- use CHAR(2) instead of varchar
CASE attendence_status when 1 then 'P' else 'A' END in the SELECT...
The code with minimal changes. Hope this helps you see how you can make similar changes in future to other code.
declare #in_date DATETIME
/*Select all the stagign entries related to promotion id and investment type id */
/* also only those staging daat related interface status tracking*/
-- Getting all distinct dates into a temporary table #Dates
SELECT a.date as full_date_of_attendence INTO #Dates
FROM dbo.getFullmonth(#in_date) a
ORDER BY a.date
-- The number of days will be dynamic. So building
-- a comma seperated value string from the dates in #Dates
SELECT #cols = COALESCE(#cols + ',', '') + [' +
CONVERT(CHAR(2), full_date_of_attendence, 106) + ']'
FROM #Dates
ORDER BY full_date_of_attendence
--select #cols
---- Building the query with dynamic dates
SET #qry =
'SELECT * FROM
(SELECT admission_id, CASE attendence_status when 1 then 'P' else 'A' END, date_of_attendence
FROM dbo.tblattendence)emp
PIVOT (MAX(attendence_status) FOR date_of_attendence IN (' + #cols + ')) AS stat'
-- Executing the query
EXEC(#qry)
-- Dropping temporary tables
DROP TABLE #Dates

How can I create a month name as a column name for a given date range in sql?

I have a data as below:
Table
country date value
------------------------------------------------------
test1 5/1/2008 500
test1 5/7/2008 200
test1 5/8/2008 300
test1 7/1/2008 100
test1 7/2/2008 100
test2 6/1/2008 100
And I want a result as below:
Result
-----------
countryName May-08 Jun-08 July-08
test1 1000 - 200
test2 - 100
This is adapted from T-SQL Pivot? Possibility of creating table columns from row values
You can see it working here: http://sqlfiddle.com/#!3/7b8c0/28
I think you might need to fiddle around with the column ordering
-- Static PIVOT
SELECT *
FROM (SELECT country,
CONVERT(char(3), date, 0) + '-' +
RIGHT(CONVERT(varchar, YEAR(date)), 2) AS date,
value
FROM country) AS D
PIVOT(SUM(value) FOR date IN([May-08],[Jun-08],[Jul-08])) AS P;
GO
-- Dynamic PIVOT
DECLARE #T AS TABLE(y INT NOT NULL PRIMARY KEY);
DECLARE
#cols AS NVARCHAR(MAX),
#y AS INT,
#sql AS NVARCHAR(MAX)
SELECT #cols = STUFF(
(SELECT N',' + QUOTENAME(y) AS [text()]
FROM (SELECT DISTINCT CONVERT(char(3), date, 0) + '-' +
RIGHT(CONVERT(varchar, YEAR(date)), 2) AS y
FROM Country
) AS Y
ORDER BY y desc
FOR XML PATH('')),
1, 1, N'')
-- Construct the full T-SQL statement
-- and execute dynamically
SET #sql = N'SELECT *
FROM (SELECT country, CONVERT(char(3), date, 0) + ''-'' +
RIGHT(CONVERT(varchar, YEAR(date)), 2) AS date, value
FROM Country) AS D
PIVOT(SUM(value) FOR date IN(' + #cols + N')) AS P;'
EXEC sp_executesql #sql
You have to use a rather complex query for that, using a LOOP it think.
For creating dynamic column names look at this post: https://stackoverflow.com/a/10926106/1321564
With sql server you have some advantages: https://stackoverflow.com/a/5638042/1321564