我需要弄清楚如何在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
答案 0 :(得分:0)
如果“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 + t.b) < 0.001
。
答案 1 :(得分:0)
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
答案 2 :(得分:0)
正如一位评论者提到的那样,你必须要有某种“排序”....我已经介绍了一个tablekey,你可以将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