回答

收藏

递归SQL中的聚合函数

技术问答 技术问答 185 人阅读 | 0 人回复 | 2023-09-13

我一直试图在SQL中解决以下迭代方程式:
5 K; `+ F1 X2 ^# U' E5 x5 i0 G: YU^{F,D}{t,p} = (\sum U^{F,D}{t-1,p} + C )*R^{F,D}_{t-1,p}: ]: S  h) p, P$ e, r
结果是:
5 E) M5 }; p: N6 ]& a$ k% W, g在此处输入图片说明1 e/ y& N0 h9 ^' L0 [9 r
我能想到的最接近的比喻是,U^{F,D}_{t,p}有一些汽车经销商() 当时有一定颜色()
+ `- `, l$ B' A7 p- Z的品牌汽车。因此,上面的等式基本上说:取 前一天(即)的汽车单位,对颜色()求和,然后 将前一天的值(,无论 是什么)相加,然后乘以其他号之前,从一天 (,不管它是什么太)。FDptt-1U^{F,D}_{t-1,p}\sum_{D}CC_{t-1,p}RR^{F,D}_{t-1,p}
" N0 A" K2 I, U4 {简化的问题
  v1 m* E( @  f- X我设法解决了上述方程式的简化形式,即:
0 U& \; T7 }7 H1 L即,不包括汽车颜色的总和(D)。示例数据和SQL, G  D0 U0 r6 u$ K( q- a
查询位于我链接的小提琴中,但我也将其粘贴在这里以供参考:3 u/ `- }3 x5 `+ N5 Q
完整数据:
9 I+ h0 R% t% B) b) [% x. qCREATE TABLE DYNAMICS ( T DATE, T_M1 DATE, P INTEGER, F VARCHAR(255), DELTA_F VARCHAR(255), R_T_M1 NUMBER, C_T_M1 NUMBER, U_T_M1 NUMBER, R_T NUMBER, C_T NUMBER, U_T NUMBER );5 z/ Q$ o0 e' |9 V
-- DAY 1, P_1  
0 L1 k! X) h; T+ m2 oINSERT INTO DYNAMICS VALUES ( TO_DATE('01.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('31.12.2014','DD.MM.YYYY HH24:MI:SS'), 1,'BMW','RED', 0.5, 0.6, NULL, 0.7,0.8,100.0 );  : t) O5 E! M' C5 s9 F
INSERT INTO DYNAMICS VALUES ( TO_DATE('01.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('31.12.2014','DD.MM.YYYY HH24:MI:SS'), 1,'MERCEDES','RED', 0.5, 0.6, NULL, 0.7,0.8,50.0 );  : P0 i& _% T  ^
-- DAY 1, P_2  & Y0 A, g1 ]9 t7 r# _
INSERT INTO DYNAMICS VALUES ( TO_DATE('01.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('31.12.2014','DD.MM.YYYY HH24:MI:SS'), 2,'BMW','RED', 0.5, 0.6, NULL, 0.7,0.8,10.0 );  
. t4 ]% D( b& v7 V& t$ tINSERT INTO DYNAMICS VALUES ( TO_DATE('01.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('31.12.2014','DD.MM.YYYY HH24:MI:SS'), 2,'MERCEDES','RED', 0.5, 0.6, NULL, 0.7,0.8,5.0 );  
7 f. V" Q2 o( {$ I9 w) {-- DAY 2, P_1  % S2 P" D0 t! Z, n% U' @. s
INSERT INTO DYNAMICS VALUES ( TO_DATE('02.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('01.01.2015','DD.MM.YYYY HH24:MI:SS'), 1,'BMW','RED', 0.7, 0.8, 100, 0.9,0.9, NULL );  ; ]4 _- ~  v6 q  x0 q+ E$ E( h
INSERT INTO DYNAMICS VALUES ( TO_DATE('02.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('01.01.2015','DD.MM.YYYY HH24:MI:SS'), 1,'MERCEDES','RED', 0.7, 0.8, 50, 0.6,0.5, NULL );  5 R! t7 H5 Z* U8 |5 C1 k) a
-- DAY 2, P_2  % k6 V; r  b& K# e. W+ H  m' {
INSERT INTO DYNAMICS VALUES ( TO_DATE('02.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('01.01.2015','DD.MM.YYYY HH24:MI:SS'), 2,'BMW','RED', 0.7, 0.8, 10, 0.7,0.8, NULL );  
8 g, n, \% p9 ~) ZINSERT INTO DYNAMICS VALUES ( TO_DATE('02.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('01.01.2015','DD.MM.YYYY HH24:MI:SS'), 2,'MERCEDES','RED', 0.7, 0.8, 5, 0.3,0.3, NULL );  
! H4 N$ s5 f: Z1 Z# K-- DAY 3, P_1  4 G& D. g; j' x, Q' {" A, C0 H2 T
INSERT INTO DYNAMICS VALUES ( TO_DATE('03.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('02.01.2015','DD.MM.YYYY HH24:MI:SS'), 1,'BMW','RED', 0.9, 0.9, NULL, 0.2,0.3, NULL );  ; s+ z$ u. s4 A* L
INSERT INTO DYNAMICS VALUES ( TO_DATE('03.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('02.01.2015','DD.MM.YYYY HH24:MI:SS'), 1,'MERCEDES','RED', 0.6, 0.5, NULL, 1.7,1.8, NULL );  
) s$ v( T  \* `: ?/ y2 M9 h2 z-- DAY 3, P_2  
: K  ^/ }8 q* _' |1 aINSERT INTO DYNAMICS VALUES ( TO_DATE('03.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('02.01.2015','DD.MM.YYYY HH24:MI:SS'), 2,'BMW','RED', 0.7, 0.8, NULL, 0.2,0.3, NULL );  
" R* D0 a# z/ o6 cINSERT INTO DYNAMICS VALUES ( TO_DATE('03.01.2015','DD.MM.YYYY HH24:MI:SS'), TO_DATE('02.01.2015','DD.MM.YYYY HH24:MI:SS'), 2,'MERCEDES','RED', 0.3, 0.3, NULL, 0.8,0.9, NULL );
. a9 x3 z: y9 _0 I! E4 Y样本数据:+ M( y) v# v+ K- D
下面演示汽车经销商p=1,F=BMW颜色汽车模型的示例数据D=RED(D从数学方程式中称为DELTASQL)。初始条件(t=0)在这里2015年1月1日。对于所有日子9 e+ N  K! c4 B+ Q/ C9 s
t,t(R_T, C_T)和t-1(R_T_M1, C_T_M1)处的所有参数均已给出。了解了这些知识后,他们的任务就是计算所有天数的汽车单位t > t=0。  {+ K- Q6 g( x# }% _
|                         T |                       T_M1 | P |   F | DELTA_F | R_T_M1 | C_T_M1 | U_T_M1 | R_T | C_T |    U_T |" A, J( t7 j* \/ X+ u9 `- f
|---------------------------|----------------------------|---|-----|---------|--------|--------|--------|-----|-----|--------|
: T0 M' r/ z% t$ j5 ~9 ]| January, 01 2015 00:00:00 | December, 31 2014 00:00:00 | 1 | BMW |     RED |    0.5 |    0.6 | (null) | 0.7 | 0.8 |    100 |+ [  o! f+ b1 L5 Z6 o) z
| January, 02 2015 00:00:00 |  January, 01 2015 00:00:00 | 1 | BMW |     RED |    0.7 |    0.8 |    100 | 0.9 | 0.9 | (null) |/ b/ U; V: g( @. |5 ?
| January, 03 2015 00:00:00 |  January, 02 2015 00:00:00 | 1 | BMW |     RED |    0.9 |    0.9 | (null) | 0.2 | 0.3 | (null) |
& K' y. m" ]& [* }  PQUERY:
2 M( h' W7 v" u8 k2 ^) Y% cIn order to resolve the simplified problem, I have come up with the query in& X5 V8 ?( I/ V& u$ z0 a
the linked fiddle that I paste here as' r! d  I1 c9 l: \1 J
well for reference:
4 `6 Q4 M: K  W2 }-- " D6 I2 `7 N0 g% s; }( u
-- SQL  T+ T' @2 z/ g3 C& ^! Y  s
-- T -> t
! Z- `+ p/ v" X5 B-- T_M1 -> t-1
) k2 Q+ R# p4 z4 W. Y" ]4 d; D& ~-- / K6 R2 ]; f+ `  q/ I$ Z2 Z, T
WITH RECU(  T, T_M1, P, F, DELTA_F,
% R& u& J: X' y% ^0 ]            R_T_M1, C_T_M1, U_T_M1, $ Y% {8 \# v) W
            R_T, C_T, U_T ) AS (  f& R. k: G& i2 _1 _2 R/ X
    -- Anchor member.
+ N% N3 N  c" C# [. W1 U7 ~: M$ D9 d" Z    SELECT  T, T_M1, P, F, DELTA_F,
: C2 x% H$ N8 ~: F; G2 ]$ n            R_T_M1, C_T_M1, 7 {! P4 S: ^$ Y
            U_T_M1, : D7 L* }& P( P4 T
            R_T, C_T, % _, @" O% d9 _) W
            U_T  z, {; _/ ^, v3 R
    FROM DYNAMICS
# m2 r  v' U6 m/ a        -- Initial condition: U_{t-1} does not exist, and U_{t=0} is given
" ]6 q5 k" F, t- ?" Z$ m  Q        WHERE  ( U_T_M1 IS NULL AND U_T IS NOT NULL )
/ J3 F, e! ]# \    UNION ALL
( L# Y- V+ w* m# t/ N    -- Recursive member.- p. y& ?( l9 U- a1 F. g
    SELECT  NEW.T, NEW.T_M1, NEW.P, NEW.F, NEW.DELTA_F,  ; G1 S. E, y1 M4 `
            NEW.R_T_M1, NEW.C_T_M1, 8 p2 K' g9 H/ H4 s# ^
            RECU.U_T AS U_T_M1,
4 q* P' M" u/ g! a; k3 m            NEW.R_T, NEW.C_T, ; E; R! A; h* Z
            -- Here the magic happens, i.e., (U_{t-1} + C_{t-1})*R_{t-1} = U_{t}8 S+ n( L  g$ J  h: i
            (RECU.U_T+NEW.C_T_M1)*NEW.R_T_M1 AS U_T1 ]4 X/ t- z" ^; ^6 q4 J  ^
    FROM DYNAMICS NEW
3 ]6 ?- B3 o0 n- D7 Q    INNER JOIN RECU3 s. C' q6 `3 k
    ON& S9 D0 K; f% ]4 W/ Y4 X
        -- Translates: yesterday (t-1) of the new record equals today (t) of the parent record% ^* H* _* y* q* c% p
        NEW.T_M1 = RECU.T AND
6 m: ~& z. S& J1 D4 `7 k. X6 T        NEW.P = RECU.P AND 1 K- @) G$ i+ x1 x$ U6 J& P3 }; h
        NEW.F = RECU.F AND 6 G: C" \/ M  u( Y: u9 T
        NEW.DELTA_F = RECU.DELTA_F
% q1 D% s1 p! o. f)# g6 b9 e9 X# y0 M: z/ ^
SELECT * FROM  RECU ORDER BY P, F, T;& i# S: w6 y' j( W5 h
This query, for the example data pasted above, results in:
8 _) O3 H7 _: h6 R! }|                         T |                       T_M1 | P |   F | DELTA_F | R_T_M1 | C_T_M1 | U_T_M1 | R_T | C_T |    U_T |  a" N# T) R& w! ]/ Y' r7 {# {, l
|---------------------------|----------------------------|---|-----|---------|--------|--------|--------|-----|-----|--------|: j0 u- O* \0 [8 b% e3 i
| January, 01 2015 00:00:00 | December, 31 2014 00:00:00 | 1 | BMW |     RED |    0.5 |    0.6 | (null) | 0.7 | 0.8 |    100 |3 e" V7 o0 H% _0 k
| January, 02 2015 00:00:00 |  January, 01 2015 00:00:00 | 1 | BMW |     RED |    0.7 |    0.8 |    100 | 0.9 | 0.9 |  70.56 |2 |* u3 b% s" _# R' I( e2 o
| January, 03 2015 00:00:00 |  January, 02 2015 00:00:00 | 1 | BMW |     RED |    0.9 |    0.9 |  70.56 | 0.2 | 0.3 | 64.314 |6 D% \- C% V- H
Which works well, i.e., for: 2015-01-02, U_t = (100+0.8)*0.7 = 70.56,  ~! s- [( h+ c1 r2 o/ v5 ^* n
2015-01-03, U_t = (70.56+0.9)*0.9 = 64.314.) Z5 N: w# a- i( V* c/ T/ p0 U
The query is written in such a way that it works with different car dealers,
; i; y; W& K% A( Pand different car brands, which can be checked running the query in the
( @9 y/ v# }: Q! V1 ulinked fiddle, \, [" ?. w" I4 F3 q( R; k6 \$ _% u
Coming back to the full problem0 C! c5 j" x. H8 C: f; F7 [
The query above cannot handle correctly the sum over cars’ colors from the6 Z: @- E& Z' _4 Z5 c4 _- w
original equation:
5 E0 E; S' A& E2 p- i$ K3 P' E3 E7 C% j8 c$ j; W+ s4 X5 ~, }- A

. H8 p3 a9 c' V1 b  u: m6 F) u7 g, A* x0 n3 Q, m
This was irrelevant in the simplified data, since all cars (BMW and MERCEDES)
$ {. ?9 }2 B2 c. I7 V$ Moccur there only in RED, and so the sum over colors effectively vanishes.7 e$ l5 P6 `. b
Such full logic should be probably implemented via a GROUP BY/SUM expression8 P5 Q* D$ V* _
built in into the original query above. Unfortunately, I do not know how to
0 K( k- V6 u% Y- fdo it.
, s* S+ Z9 O4 n* n! p$ |# ?/ c% P
So, imagine you have data in the shape like in the simplified problem section,( K2 K$ C* p6 Z. s7 h) y, e1 ]
but now every car brand exists in two colors, e.g., like in this linked* G, s0 k# _( E- J7 t. |9 j+ f. W
fiddle:
  ]4 s* _) ~. F! `0 B" C|                         T |                       T_M1 | P |        F | DELTA_F | R_T_M1 | C_T_M1 | U_T_M1 | R_T | C_T |    U_T |
$ |- L. ^4 w; |: ?' q* I9 I% k|---------------------------|----------------------------|---|----------|---------|--------|--------|--------|-----|-----|--------|5 E( z6 u1 n) N5 Q
| January, 01 2015 00:00:00 | December, 31 2014 00:00:00 | 2 | MERCEDES |   BLACK |    0.2 |    0.6 | (null) | 0.5 | 0.8 |    5.5 |
% V' \3 [$ |, J2 N) u& n* I| January, 01 2015 00:00:00 | December, 31 2014 00:00:00 | 2 | MERCEDES |     RED |    0.5 |    0.6 | (null) | 0.7 | 0.8 |      5 |
/ Y0 w) s$ M/ e/ l' |4 G9 b6 p| January, 02 2015 00:00:00 |  January, 01 2015 00:00:00 | 2 | MERCEDES |   BLACK |    0.5 |    0.8 |    5.5 | 1.3 | 0.5 | (null) |' r' Y' D; M8 M5 X- n; s* r
| January, 02 2015 00:00:00 |  January, 01 2015 00:00:00 | 2 | MERCEDES |     RED |    0.7 |    0.8 |      5 | 4.3 | 0.5 | (null) |
" t/ {% H! |, N6 }3 p. k. ~. x) `| January, 03 2015 00:00:00 |  January, 02 2015 00:00:00 | 2 | MERCEDES |   BLACK |    1.3 |    0.5 | (null) | 0.3 | 0.9 | (null) |& N* b- Z+ j$ h3 L; R$ ~+ W8 e
| January, 03 2015 00:00:00 |  January, 02 2015 00:00:00 | 2 | MERCEDES |     RED |    4.3 |    0.5 | (null) | 0.4 | 0.9 | (null) |* y' [; e1 e) |4 l; T1 W- }
Given such data, you would expect for the dealer p=2 F=MERCEDES cars
2 b8 B3 e$ N( R1 P- G2 }$ `) S9 w% cdynamics to look as follows:. P8 Z5 p- X1 ^' ?9 d
U^{MERCEDES,BLACK}_{T=2015-01-02,P=2} = ( (5.5 + 5) + 0.8 )*0.5 = 11.3*0.5 = 5.65
2 F. U1 ~, d, v6 h8 x/ LU^{MERCEDES,RED}_{T=2015-01-02,P=2} = ( (5.5 + 5) + 0.8 )*0.7 = 11.3*0.7 = 7.91
9 _' {; A" u9 s& i! yU^{MERCEDES,BLACK}_{T=2015-01-03,P=2} = ( (5.65 + 7.91) + 0.5 )*1.3 = 14.06*1.3 = 18.278+ N, B/ i1 c( B% I# s: I& y
U^{MERCEDES,RED}_{T=2015-01-03,P=2} = ( (5.65 + 7.91) + 0.5 )*4.3 = 14.06*4.3 = 60.4586 W  A. i$ \1 c7 P0 B5 p5 d/ Y7 g
Question is how the simplified query above should be adjusted to solve this
* V* U! S3 m1 @7 z3 ^6 R  X) b& ~problem.

7 V) o: V- x8 O2 V3 [# s                - i3 b5 [7 |! I$ k& D1 z
解决方案:
% b; t4 f5 H' f( i. L( ~9 d3 ^                3 W7 ?" K) V6 `6 }+ n

3 X$ d, d9 ]. s: M) G. Y, \- ?& X8 ~# q/ ~( ]% I) `
                I do not think this is the best answer but I think it gives you the result! C! m% U; Z' }) S; H4 s# s6 f
that you are looking for.2 q3 V2 ]4 R1 q, d" o# Z. p3 ?
WITH RECU(  T, T_M1, P, F, DELTA_F,
  C7 M% `2 C. I' S7 g            R_T_M1, C_T_M1, U_T_M1, 0 [0 @  N% @, v5 ?6 o
            R_T, C_T, U_T ) AS (
$ k6 H3 x2 E! d, Y* n    -- Anchor member.
, K4 ~) U$ d: b7 m& y0 [  C! ?" S    SELECT  T, T_M1, P, F, DELTA_F,
" \/ j0 S  f, ^6 r: J            R_T_M1, C_T_M1, * @# U& D5 S7 I, m7 R, L) z
            U_T_M1, " C5 O* T6 V5 J8 X( `* E2 C+ i& x- L
            R_T, C_T, ' y' \# T* ~5 R2 j7 W/ T/ X
-- Start SUM of u_t7 D8 J& Q8 d# C9 g0 i
              (select sum(u_t) from DYNAMICS d21 R! e* a, B; f  G/ ~. N3 }
               where d2.T=d1.T and d2.T_M1=d1.T_M1 and d2.P=d1.P and d2.F=d1.F
& i0 E: l& A2 \% r1 r+ x               group by T, T_M1, P, F) as u_t$ K: P! Q: _1 Y: O: c. |
-- End SUM of u_t   
( S8 @1 ^5 I+ d    FROM DYNAMICS d1
' `' h  o- A! i) B        -- Initial condition: U_{t-1} does not exist, and U_{t=0} is given
3 R5 G& B1 q* u7 }" k- N: N8 h        WHERE  ( U_T_M1 IS NULL AND U_T IS NOT NULL )
2 a- D+ ~7 F& E/ [) E    UNION ALL0 @( L7 q" q3 V# d) U2 Z; l# U
    -- Recursive member.! h0 y! Y+ Z5 y8 r/ V$ l
    SELECT  NEW.T, NEW.T_M1, NEW.P, NEW.F, NEW.DELTA_F,  4 J# S! B( |9 y' q; s
            NEW.R_T_M1, NEW.C_T_M1, 2 R: q  v: e+ j7 o! \3 P
            RECU.U_T AS U_T_M1,+ Z6 ]- @7 t, H5 z
            NEW.R_T, NEW.C_T
3 Q9 O* q- E4 \              ,
) B, ^2 K  d/ {( d0 Y6 ]' h* L+ M            -- Here the magic happens, i.e., (U_{t-1} + C_{t-1})*R_{t-1} = U_{t}
  I: \1 Y; }0 j3 i' X; M9 e! O            (
) ]  b# F( d* D8 m. D5 `3 y& W$ {  b              RECU.U_T; q. o6 u/ X6 P0 e; E# T
              +NEW.C_T_M1)*NEW.R_T_M1 AS U_T
, }9 j: `  X1 }3 m/ m0 q    FROM DYNAMICS NEW 8 N6 D+ G9 q3 D) T9 Q; q) b0 Z, B
    INNER JOIN RECU5 M: o2 m8 x9 S
    ON
" O% m& y7 X# ]* P1 m) B* z2 {        -- Translates: yesterday (t-1) of the new record equals today (t) of the parent record  b0 K- U  y2 r
        NEW.T_M1 = RECU.T AND
3 B; n" [% h2 D, Z; |& E        NEW.P = RECU.P AND & O. b& L$ ]" S) D( m$ u
        NEW.F = RECU.F AND
9 F: q. }4 r8 h  s        NEW.DELTA_F = RECU.DELTA_F
) w  ~7 @' \, f+ T& G9 ~. I# T  J4 w)  \" ^: R: e. H7 m6 o
SELECT * FROM  RECU ORDER BY P, F, T;
6 a$ n1 @) _$ \( X7 ]$ ~! _' z. YWhat i’ve added is between Start SUM of u_t and End SUM of u_t comments/ L2 \) J- ^2 k6 M8 g
and here is the fiddle.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则