Reputation: 11
Suppose that I start off with 'Table a'
+-----------+
|iD | Value |
|-----------|
| 0 | 1 |
| 1 | 5 |
| 2 | 6 |
| 3 | 8 |
+-----------+
I then want to create an SQL query that will show the iD, the Value, the Value numerically closest to the current value & the difference between these values e.g
+-----------+------------+------------+
|iD | Value | closestVal | Difference |
|-----------|------------|------------+
| 0 | 1 | 5 | 4 |
| 1 | 5 | 6 | 1 |
| 2 | 6 | 5 | 1 |
| 3 | 8 | 6 | 2 |
+-----------+------------+------------+
From researching I think it may include using something along the lines of ABS(a.Value - b.Value) assuming negative numbers are a possibility although I'm not sure exactly how the referencing of the current row and the comparative rows are handled as well as the output of one value and not a table of values for each comparison.
How would I go about doing this? Any help would be appreciated
Upvotes: 1
Views: 353
Reputation: 1269493
I think the easiest way to approach this is with a correlated subquery:
select t.*, abs(closestvalue - value) as difference
from (select t.*,
(select t2.value
from tablea t2
order by abs(t2.value - t.value) asc
limit 1
) as closestvalue
from tablea t
) t;
You can also do this an explicit join
, but the logic is a little strange:
select a.id, a.value,
(case when min(case when a.value > a1.value then a.value - a1.value end) = min(abs(a.value - a1.value))
then a.value - min(abs(a.value - a1.value))
else a.value + min(abs(a.value - a1.value))
end) as closestvalue
min(abs(a.value - a1.value)) as difference
from tablea a join
tablea a1
on a.id <> a1.id
group by a.id;
Using this approach, the difference is easy to find, by using min(abs())
. The problem is then figuring out whether the closest value is bigger or less than the value. The logic here figures it out using conditional aggregation and comparing those results to the actual minimum.
Upvotes: 2