这是一个示例表,我希望得到每个id的所有负数和最小正数(包括0)
declare @tbl table(id INT, value decimal, someData varchar(10))
insert into @tbl
values(1,-3,123),(1,-2,234),(1,-1,345),(1,3,456),(1,4,567),(2,-4,678),(2,-2,789),(2,1,890),(2,2,135),(3,-5,246),(3,10,357)
select * from @tbl where value < 0 union
select id, min(value),someData from @tbl WHERE value > 0 group by id,somedata
我试图通过分离缺点和优点找到解决方案。但由于某些数据,我无法按需要分组。
期望的结果是:
1 -3 123
1 -2 234
1 -1 345
1 3 456
2 -4 678
2 -2 789
2 1 890
3 -5 246
3 10 357
这也是一个漫长的工作查询,所以我不想做双选。是否可以在一个选择中进行?
答案 0 :(得分:1)
这应该有效:
;With separated as (
select *,ROW_NUMBER() OVER (PARTITION BY SIGN(value),id ORDER BY value) as rn
from @tbl
)
select * from separated where SIGN(value) < 0 or rn=1
如果value
为0,您还没有说明会发生什么情况,所以如果您的数据包含某些内容,则上述内容可能正确也可能不正确。
SIGN
在SQL Server中是一个很少使用但偶尔有用的函数,返回-1,0或+1,并允许我们轻松地将数组分成3组。
答案 1 :(得分:0)
使用Window function
你可以得到最小值。并使用UNION
来组合结果。试试这个..
;WITH CTE
AS (SELECT Row_number() OVER (PARTITION BY ID ORDER BY value) RN, *
FROM @tbl
WHERE value > 0)
SELECT *
FROM @tbl
WHERE value < 0
UNION ALL
SELECT ID,value,someData
FROM CTE
WHERE RN = 1
答案 2 :(得分:0)
使用联合来组合条件可能是最容易的。但是要选择具有最小正值的行需要子查询,并假设ID是唯一标识符:
select id,value,somdata from @tbl where value < 0
union
select id,value,somdata from @tbl
where value = (select min(value) from @tbl where value > 0)
(这不会包含零值的行,但问题并不是说它们应该落在哪一侧。)
答案 3 :(得分:0)
使用OR where子句将其作为单个选择进行攻击,使用子查询获取最小正数:
select * from @tbl
where value < 0
or value = (
select min(value)
from @tbl
where value > 0)