簡體   English   中英

基於多行的SQL查詢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM