[英]SQL query based on multiple rows
我需要弄清楚如何使它在SQL中起作用:
如果C = 1,則在C = 1的行中找到B是B的負數的下一行,並且兩行的A值都相同。 如果這兩行之間的D差大於1天,則返回C = 1的那一行
樣本數據
A B C D
1 10.00 0 2015-01-01
1 15.00 1 2015-01-02
1 -15.00 0 2015-01-03
2 5.00 1 2015-01-03
2 -5.00 0 2015-01-05
3 1.00 1 2015-01-03
3 2.00 0 2015-01-04
3 -1.00 0 2015-01-05
預期產量:
2 5.00 1 2015-01-03
3 1.00 1 2015-01-03
如果用“ next”表示在d列中有一個更高的值,那么您可以將條件轉換為exists
子句:
select t.*
from table t
where t.c = 1 and
exists (select 1
from table t2
where t2.d >= datedadd(day, 1, t.d) and t2.a = t.a and
t2.b = - t.b
);
注意:如果b
是浮點數,則可能需要公差,例如abs(t2.b + tb) < 0.001
。
select m1.*
from myTable m1
inner join myTable m2
on m1.a = m2.a -- same a
and m1.b = m2.b * -1 -- b is the negative of b
and m1.d < m2.d -- the next row
and dateadd(day, 1, m1.d ) > m2.d -- difference is greater than 1 day
where m1.c = 1
union all
select m2.*
from myTable m1
inner join myTable m2
on m1.a = m2.a
and m1.b = m2.b * -1
and m1.d < m2.d
and dateadd(day, 1, m1.d ) <= m2.d
where m1.c = 1
正如一個評論者所暗示的那樣,您必須具有某種“排序” ....我已經引入了一個表鍵,您可以將Over / OrderBY更改為已經存在的某種東西...但是您還必須具有某種排序機制“他們來了”。
我並不是說我的查詢是最短的查詢...但是,當我有“笨拙的業務規則”時,我會選擇簡潔而不是簡潔,所以如果我必須回頭並保持它,我可以分解“部分”以某種方式有意義。
這是一個答案,可以使您大部分都在那里。 基本上,我會根據您的條件去釣魚“ MagicNewRow”。 但這僅能起作用,因為我能夠通過某種排序機制來創建ComputedRowId。 (正如我之前解釋的)
declare @holder table (TableKey int identity(1,1) ,
Col1 int, Col2 decimal, Col3 bit , Col4 smalldatetime , ComputedRowID int )
insert into @holder (Col1, Col2, Col3, Col4)
select 1 , 10.00 , 0, '2015-01-01'
union all select 1 , 15.00,1, '2015-01-02'
union all select 1 , -15.00, 0, '2015-01-03'
union all select 2 , 5.00, 1, '2015-01-03'
union all select 2 , -5.00, 0, '2015-01-05'
union all select 3 , 1.00, 1, '2015-01-03'
union all select 3 , 2.00, 0, '2015-01-04'
union all select 3 , -1.00, 0, '2015-01-05'
--select * from @holder
Update @holder Set ComputedRowID
= derived1.ROWID
from
@holder hold join
--Select * from
(
select TableKey, Col1, Col2, Col3, Col4 , ROW_NUMBER() over (order by TableKey) as ROWID
from @holder) as derived1
on hold.TableKey = derived1.TableKey
/*
f C=1 then find the next row where B is the negative of B in the row
where C=1 and the value of A is the same for both rows.
If the difference in D between those 2 rows is greater than 1 day,
then return that row where C=1*/
;WITH
cteCIsOne /*Col1, Col2, Col3, Col4, ROWID )*/
AS
(
Select holderAlias.Col1, holderAlias.Col2, holderAlias.Col3, holderAlias.Col4, holderAlias.ComputedRowID
from @holder holderAlias
where Col3 = 1
)
,
cteRowsGreaterThanCurrentRowIdAndNegRuleApplies /*(Col1, Col2, Col3, Col4, ROWID )*/
AS
(
Select holderAlias.Col1, holderAlias.Col2, holderAlias.Col3, holderAlias.Col4,
holderAlias.ComputedRowID,
MagicNextRowComputedRowID = (select top 1 ComputedRowID from cteCIsOne cte1
where holderAlias.ComputedRowID > cte1.ComputedRowID and holderAlias.col2 = (-1 * cte1.col2) )
from @holder holderAlias
)
Select Col1, Col2, Col3, Col4 , ComputedRowID , MagicNextRowComputedRowID, MagicNextRowDate
, MyDateDiff = datediff(d, MagicNextRowDate, Col4)
from
(
SELECT Col1, Col2, Col3, Col4 , ComputedRowID , MagicNextRowComputedRowID
,
MagicNextRowDate = (select top 1 Col4 from @holder hold where hold.ComputedRowID = cteAlias2.MagicNextRowComputedRowID)
from cteRowsGreaterThanCurrentRowIdAndNegRuleApplies cteAlias2
) as derived
where derived.MagicNextRowComputedRowID IS NOT NULL
and
datediff(d, MagicNextRowDate, Col4) > 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.