Reputation: 23
I have searched quite extensivly for the answer to my question but without succes. To be honest, I don't really know what the solution would look like, hence difficult to make a good search.
So, I have declared a table variable at the start of my Stored Procedure. This table gets some static data from another table. This way I don't always have to reload the original table (correct me if I'm wrong please). This table contains 6 columns; A, B, C, D, E, F (30, 60, 90, 180, 360, 9999).
It looks somehting like this right now:
DECLARE @VALUES TABLE (A INT, B INT, C INT, D INT, E INT, F INT);
INSERT INTO @VALUES(A, B, C, D, E, F)
SELECT A, B, C, D, E, F
FROM SOME_TABLE as RV
WHERE ID = 1;
Now I want to iterate through this table to match a value with the correct table. I can use IF statements but that seems like it is more work then needed and not really performance minded. I will give an example:
My value X equals 61. I want to match this with the correct column (A, B, C, ...). For this number it would be colomn C, since 61 is larger then 60 (B) and smaller then 90 (C).
Everything smaller then 30 goes into A, smaller then 60 -> B, ...
Can anyone help me with this? And tell me where to look for the must optimal solution to my problem.
Thanks in advance!
Upvotes: 0
Views: 113
Reputation: 1986
Instead of having a single column table with delimiters, you could define table with ranges:
DECLARE @VALUES TABLE (Name VARCHAR(20), Min INT, Max INT);
INSERT INTO @VALUES(Name, Min, Max)
SELECT 'Category 1' As Name, 0 as Min, A as Max
FROM SOME_TABLE WHERE ID = 1;
INSERT INTO @VALUES(Name, Min, Max)
SELECT 'Category 2' As Name, A as Min, B as Max
FROM SOME_TABLE WHERE ID = 1;
INSERT INTO @VALUES(Name, Min, Max)
SELECT 'Category 3' As Name, B as Min, C as Max
FROM SOME_TABLE WHERE ID = 1;
...
Then you could join on this table:
SELECT X.X, V.Name
FROM XValues X JOIN @VALUES V on X.X >= V.Min AND X.X < V.Max
Upvotes: 3
Reputation: 29647
If you only need to calculate 1 value against that table, then you can set it directly with a select.
For example:
declare @value int = 61;
declare @classvalue int;
set @classvalue = (select top 1
(case
when @value > E then F
when @value > D then E
when @value > C then D
when @value > B then C
when @value > A then B
when @value > 0 then A
else null
end) as classvalue
from @VALUES);
select @classvalue;
Actually, in that example you could directly select from the table instead of first putting the record in @VALUES.
Upvotes: 0
Reputation: 1269503
You can do this using outer apply
:
select top 1 v.*
from @values val outer apply
(values (A, 'A'), (B, 'B'), (C, 'C'), (D, 'D'), (E, 'E'), (F, 'F')
) v(val, name)
where val <= @YourValue
order by val desc;
The advantage of this approach is that it is easy to include the column name as well as the value.
Upvotes: 0
Reputation: 67291
The question is quite unclear and the whole approach smells... If you are fix with columns A to F (and your question seems to be like this), you might go this way:
DECLARE @SomeValues TABLE(Val INT);
INSERT INTO @SomeValues VALUES(1),(30),(61),(180),(181);
DECLARE @VALUES TABLE (A INT, B INT, C INT, D INT, E INT, F INT);
INSERT INTO @VALUES VALUES(30, 60, 90, 180, 360, 9999);
SELECT sv.Val
,CASE WHEN sv.Val<=v.A THEN v.A
WHEN sv.Val<=v.B THEN v.B
WHEN sv.Val<=v.C THEN v.C
WHEN sv.Val<=v.D THEN v.D
WHEN sv.Val<=v.E THEN v.E
WHEN sv.Val<=v.F THEN v.F END AS Corresponding
FROM @SomeValues AS sv
CROSS JOIN @VALUES AS v
You might return the column's name instead of the value by using THEN 'A'
instead of THEN v.A
(and further down...)
Upvotes: 1