Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Query

Author  Topic 

smh
Yak Posting Veteran

94 Posts

Posted - 2012-05-04 : 23:07:34
Hi All:
In a table we have 9 columns in each row
Let us call these columns Level1, Level2, …Level9
There are numerical values (decimal) in each of these columns.
Some values may be 0.
The values are in descending order. Thus Level1>=Level2 >=Level3 etc.


For a numerical integer parameter, P, that may have a value from 1 to 9, we must obtain for each row in the table the first non-zero value in columns named Level P or less, traversing the columns in descending sequence of column name

For example, if P=5, and the values in Row17 are
Level1 3.85
Level2 3.80
Level3 0
Level4 0
Level5 0
Level6 0
Level7 2.65
Level8 0
Level9 2.25

Then the function should return 3.80


And if P=5 and the values in Row 18 are
Level1 3.65
Level2 3.60
Level3 0
Level4 0
Level5 3.40
Level6 0
Level7 2.45
Level8 2.35
Level9 0
Then the function should return 3.40

If all values are 0, the function should return 0
The value P will be the same for each row (here it is 5)

I have just been going thru each column with an "if" statement to see if the level is <= value P and then capturing the decimal value (if greater than 0) in a variable. I have to check each level up to level 9 even if P is < 9 because I am not "looping" thru the columns and don't know if that is possible.

Any help appreciated.
Thanks Everyone.

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2012-05-05 : 01:05:18
i think best way to do is to first apply unpivot and then do the searxh

like


;With CTE
AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY RowID ORDER BY Col DESC) AS Rn,Val,Col,RowID
FROM table t
UNPIVOT(Val FOR Col IN ([Col1],[Col2],...[Col9]))u
)

SELECT RowID,COALESCE(Val,0)
FROM (SELECT DISTINCT RowID FROM CTE)c
OUTER APPLY (SELECT Top 1 Val
FROM CTE
WHERE Val >0
AND RowID = c.RowID
ORDER BY Rn)c1


------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

RL
Starting Member

15 Posts

Posted - 2012-05-05 : 14:11:37
Nice UNPIVOT example. I used an old-school subquery (still learning {CROSS|OUTER APPLY}). Lower optimizer cost because it doesn't need the ROW_NUMBER() column in CTE. Still defaults to zero using COALESCE.

Below is code for a scalar function (returns a single value) with params @row_id and @col_name. Syntax: SELECT dbo.fn_get_value(@row_id, @col_name)
NOTE: Avoid using scalar functions in WHERE or JOIN, use inline function (returns result set) instead for better performance.

CREATE FUNCTION dbo.fn_get_value
(
@row_id INT,
@col_name VARCHAR(50)
)
RETURNS DEC(5,2)
AS
BEGIN
DECLARE @value DEC(5,2);

With CTE
AS
(
SELECT RowID, Col, Val
FROM table
UNPIVOT(Val FOR Col IN (Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9)) u
)
SELECT @value = Val FROM CTE C1
WHERE RowID = @row_id
AND Col = COALESCE((SELECT MAX(Col) FROM CTE
WHERE Val > 0.
AND RowID = C1.RowID
AND Col <= @col_name), 'Col1');
RETURN (@value);
END
GO

Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2012-05-05 : 14:17:02
actually you dont need rownumber if col values are alphabetical. I just added it for extra safety

even this would suffice



;With CTE
AS
(
SELECT Val,Col,RowID
FROM table t
UNPIVOT(Val FOR Col IN ([Col1],[Col2],...[Col9]))u
)

SELECT RowID,COALESCE(Val,0)
FROM (SELECT DISTINCT RowID FROM CTE)c
OUTER APPLY (SELECT Top 1 Val
FROM CTE
WHERE Val >0
AND RowID = c.RowID
ORDER BY Col DESC)c1


------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

RL
Starting Member

15 Posts

Posted - 2012-05-05 : 18:46:18
Using TOP 1, I agree it's best to sort rather than assume they are naturally in order. But it turns out the ROWNUM column in CTE is not the main cause of the extra optimizer cost after all. Most of it is from ORDER BY, which isn't necessary with MAX(Col). (Not that I knew that when I wrote it! :) )
Go to Top of Page

smh
Yak Posting Veteran

94 Posts

Posted - 2012-05-06 : 01:19:41
Hi everyone.

I am looking at all of these, trying to understand, and will soon try them out on my work problem at the beginning of the week. I thank you all. This is very complicated for me, even though simply and elegantly put in the code examples. I have never used the coalsce or the pivot, unpivot, or rownumber() partitian. In this case I am using 9 if statements in the select statment on each row so I hope to your examples lead to a better way. By the way , the field names in my case are price1, price2, price3...price9
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2012-05-06 : 13:26:10
quote:
Originally posted by smh

Hi everyone.

I am looking at all of these, trying to understand, and will soon try them out on my work problem at the beginning of the week. I thank you all. This is very complicated for me, even though simply and elegantly put in the code examples. I have never used the coalsce or the pivot, unpivot, or rownumber() partitian. In this case I am using 9 if statements in the select statment on each row so I hope to your examples lead to a better way. By the way , the field names in my case are price1, price2, price3...price9


understand them here

http://www.codeproject.com/Articles/193842/Working-with-Pivot-and-UnPivot-Transformation

http://www.databasejournal.com/features/mssql/article.php/3572301/RowNumber-function-in-SQL-Server-2005.htm

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page
   

- Advertisement -