June 8, 2012 at 2:56 pm
There are two tables A and B as below.
TABLE A:
NAME201202201203201204
BBB------37038---39188----23172
AAA-----34204---41337----21618
TABLE B:
Name201202201203201204
BBB-----5-------6--------7
AAA-----3-------9--------4
How to do math job with this two table for project's automation?
I need result like below
A.201202/B.201202 AS 201202AVERAGE
A.201203/B.201203 AS 201203AVERAGE
A.201204/B.201204 AS 201204AVERAGE
Since these two tables are created using crosstab query, column's name will change dynamacly.
For example, next month column's name will change to 201203,201204,201205
June 8, 2012 at 3:06 pm
With dynamic sql.
If you want some real help post some ddl, sample data and desired output.
_______________________________________________________________
Need help? Help us help you.
Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.
Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.
Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/
June 8, 2012 at 11:16 pm
You could use unpivot in this case as follows:
--Creating Tables
Create Table A
(NAME varchar(3),
[201202] int,
[201203] int,
[201204] int )
Create Table B
(NAME varchar(3),
[201202] int,
[201203] int,
[201204] int )
--Inserting Sample Data
Insert into A
Select 'BBB', 37038, 39188, 23172
Union ALL
Select 'AAA', 34204, 41337, 21618
Insert Into B
Select 'BBB', 5, 6, 7
Union ALL
Select 'AAA', 3, 9, 4
--Static UnPivot Type1
Select NAME, Years, Average From
(Select A.NAME, (A.[201202]/B.[201202]) As [201202], (A.[201203]/B.[201203]) As [201203], (A.[201204]/B.[201204]) As [201204] From A
Join B ON A.NAME = B.NAME) As p
Unpivot
(Average For Years IN ([201202], [201203], [201204])) As u
Order By NAME
--Static UnPivot Type2
Select x.NAME, x.Years, (x.Value/y.Value) As Average From
(Select NAME, Years, Value From
(Select NAME, [201202], [201203], [201204] From A) As p
Unpivot
(Value For Years In ([201202], [201203], [201204])) As u) As x
JOIN
(Select NAME, Years, Value From
(Select NAME, [201202], [201203], [201204] From B) As p
Unpivot
(Value For Years In ([201202], [201203], [201204])) As u) As y ON x.NAME = y.NAME AND x.Years = y.Years
Order By x.NAME
--Dynamic UnPivot
Declare @cols varchar(max), @sql varchar(max)
Declare @temp Table(Cols varchar(max))
Insert Into @temp
Select Distinct x.Years From
(Select NAME, Years, Value From
(Select NAME, [201202], [201203], [201204] From A) As p
Unpivot
(Value For Years In ([201202], [201203], [201204])) As u) As x
JOIN
(Select NAME, Years, Value From
(Select NAME, [201202], [201203], [201204] From B) As p
Unpivot
(Value For Years In ([201202], [201203], [201204])) As u) As y ON x.NAME = y.NAME AND x.Years = y.Years
Select @cols = Coalesce(@cols + ', ', '') + QUOTENAME(Cols) From @temp
Set @sql = 'Select x.NAME, x.Years, (x.Value/y.Value) As Average From
(Select NAME, Years, Value From
(Select NAME, '+@cols+' From A) As p
Unpivot
(Value For Years In ('+@cols+')) As u) As x
JOIN
(Select NAME, Years, Value From
(Select NAME, '+@cols+' From B) As p
Unpivot
(Value For Years In ('+@cols+')) As u) As y ON x.NAME = y.NAME AND x.Years = y.Years
Order By x.NAME'
Execute (@sql)
You could do the Static Unpivot in two ways as shown in the above code. You could either JOIN the tables and then Unpivot the result set or you can Unpivot the two tables and then do a JOIN.
In the Static sense I think that the "Static Unpivot type1" is easier.
But, while applying it Dynamically I found that "Static Unpivot Type2" was easier to apply Dynamically.
Hope this was what you were looking for.
June 9, 2012 at 10:37 am
adonetok (6/8/2012)
Since these two tables are created using crosstab query, column's name will change dynamacly.For example, next month column's name will change to 201203,201204,201205
The key here is that you're trying to do a calculation AFTER it has been formatted for display using the CROSS TAB. Do the Average calculation BEFORE you do the CROSS TAB.
--Jeff Moden
Change is inevitable... Change for the better is not.
June 10, 2012 at 10:33 pm
Jeff is right, but if you can't change to do what he's saying, then you can also do it this way.
CREATE TABLE #TABLEA (Name VARCHAR(3), [201202] INT, [201203] INT, [201204] INT)
CREATE TABLE #TABLEB (Name VARCHAR(3), [201202] INT, [201203] INT, [201204] INT)
INSERT INTO #TABLEA
SELECT 'BBB', 37038, 39188, 23172
UNION ALL SELECT 'AAA', 34204, 41337, 21618
INSERT INTO #TABLEB
SELECT 'BBB', 5, 6, 7
UNION ALL SELECT 'AAA', 3, 9, 4
-- Static UNPIVOT without using UNPIVOT
SELECT a.Name, Date, Avg
FROM #TABLEA a
INNER JOIN #TABLEB b ON a.Name = b.Name
CROSS APPLY (
SELECT 1. * a.[201202] / b.[201202], 1. * a.[201203] / b.[201203], 1. * a.[201204] / b.[201204]
) x([201202], [201203], [201204])
CROSS APPLY (
VALUES ('[201202]', x.[201202]), ('[201203]', x.[201203]), ('[201204]',x.[201204])) y (Date, Avg)
DECLARE @sql VARCHAR(MAX)
-- Dynamic UNPIVOT with date column names taken from Dates CTE
;WITH Dates (d) AS (SELECT '[201202]' UNION ALL SELECT '[201203]' UNION ALL SELECT '[201204]')
SELECT @sql = '
SELECT a.Name, Date, Avg FROM #TABLEA a INNER JOIN #TABLEB b ON a.Name = b.Name
CROSS APPLY (
SELECT ' +
STUFF(
(SELECT ',1.*a.' + d + '/b.' + d
FROM Dates
FOR XML PATH(''), root('MyString'), type
).value('/MyString[1]','varchar(max)' )
, 1, 1, '') + ')x(' +
STUFF(
(SELECT ',' + d
FROM Dates
FOR XML PATH(''), root('MyString'), type
).value('/MyString[1]','varchar(max)' )
, 1, 1, '') + ') CROSS APPLY ( VALUES ' +
STUFF(
(SELECT ',(''' + d + ''', x.' + d + ')'
FROM Dates
FOR XML PATH(''), root('MyString'), type
).value('/MyString[1]','varchar(max)' )
, 1, 1, '') + ') y (Date, Avg)'
--SELECT @sql
EXEC (@SQL)
DROP TABLE #TABLEA, #TABLEB
My thought question: Have you ever been told that your query runs too fast?
My advice:
INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.
Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
Since random numbers are too important to be left to chance, let's generate some![/url]
Learn to understand recursive CTEs by example.[/url]
[url url=http://www.sqlservercentral.com/articles/St
Viewing 5 posts - 1 through 4 (of 4 total)
You must be logged in to reply to this topic. Login to reply