2014-11-06 21 views
0

這樣的例子表的最小正數,我想所有的負數和最小正數(0含稅),每ID列出所有負數,並從表

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 

也是其長期工作的查詢,所以我不想做雙選。是否有可能在一個選擇?

回答

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組。

+0

對不起,我忘了提0.編輯畝問題。與您的解決方案,它不會帶來積極的每個ID。比較時可能需要檢查ID? – Rapunzo 2014-11-06 09:40:21

+0

@Rununzo - 更新爲'id'。只需將其添加到「PARTITION」子句即可。 – 2014-11-06 09:41:44

+0

非常感謝。成功了! – Rapunzo 2014-11-06 09:42:41

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 
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) 

(這將不包括與零值的行,但問題沒有按」牛逼說,他們應屬於哪一方)

0

攻擊它作爲一個單一的與或WHERE子句中選擇,使用子查詢,以獲得最小正數。

select * from @tbl 
where value < 0 
or value = (
    select min(value) 
    from @tbl 
    where value > 0) 
相關問題