在Oracle中将某列上方所有varchar值连接在一起。

huangapple go评论93阅读模式
英文:

Concatenate all varchar values of a column above a row in oracle

问题

I'll provide a translation of the content you provided:

我有一个使用情况,在其中有一列存储一些字符、flg列和一个category列。
根据flg,如果flg为1,则对于第i行,res1应该是第i行上方的行的字符连接(用''+''连接),以及第i行的Column1值。“上方的第i行”意味着SEQNCE<SEQNCE(i)。

如果flg为零,则res1=Column1。对行上方的连接仅限于Category相同的情况,如果Category发生变化(例如,Category=2 Column1='I'是一个新集合),则应从那一行开始连接的过程。

例如,下面是名为'dmy_tbl'的表格:

LISTAGG是一种用于按其他列分组连接字符串的选项,而LAG是用于获取行上方行的选项,我尝试了下面的查询,但没有得到预期的结果。而且我无法决定如何根据category分区。对于这个使用情况,欢迎任何建议。

select column1,catg,flg,SEQNCE,
case when ((flg=1 and res is null) or flg=0) then column1
else column1||'+'||res end as result
from
(select column1,catg,flg,SEQNCE,
case when flg=1 then lag(column1) 
over(order by catg,SEQNCE asc) else column1 end as res 
FROM dmy_tbl
order by catg,SEQNCE asc);

内部查询中,res列仅获取上面的一行,不确定如何将LISTAGG嵌入到内部查询中以获取所有上面的行。

英文:

I have a use case wherein there is a column which stores some characters, flg column and a category column.
Based on flg, if flg is 1 then for ith row the res1 should be concatenation of characters (concatenated by ''+'') of rows above the ith row and the ith row Column1 value. "Above ith row" meaning SEQNCE<SEQNCE(i).

If flg is zero then res1=Column1. This concatenation of rows above a row is limited only until category is same, if Category changes(eg. Category=2 Column1='I' is a new set) it should start from that row the process of concatenation.

For eg. below is the table named ''dmy_tbl''

在Oracle中将某列上方所有varchar值连接在一起。

LISTAGG is one such option to concatenate strings group by other column & LAG is option for fetching rows above a row, I have tried below query but it does not yield expected result. Also I'm not able to make a decision on how to partition on category. Any suggestion for this use case is highly welcomed.

select column1,catg,flg,SEQNCE,
case when ((flg=1 and res is null) or flg=0) then column1
else column1||&#39;+&#39;||res end as result
from
(select column1,catg,flg,SEQNCE,
case when flg=1 then lag(column1) 
over(order by catg,SEQNCE asc) else column1 end as res 
FROM dmy_tbl
order by catg,SEQNCE asc);

在Oracle中将某列上方所有varchar值连接在一起。

The inner query, res column is only fetching one row above, not sure on how to fit in LISTAGG in the inner query to fetch all above rows

答案1

得分: 1

你可以使用 MODEL 子句:

选择 列1,
       指示器,
       序列,
       类别,
       CASE 指示器
       当 0
       然后 列1
       否则 结果
       结束 AS 结果1
从   dmy_tbl
模型
  按 (类别) 分区
  按 (序列) 维度
  度量 (
    列1,
    指示器,
    CAST(NULL AS VARCHAR2(4000)) AS 结果
  )  
  规则 (
    结果[1] = 列1[1],
    结果[序列>1] = 结果[cv()-1] || '+' || 列1[cv()]
  );

对于示例数据:

创建表 dmy_tbl (列1, 指示器, 序列, 类别) 作为
选择 'A', 1, 1, 1 FROM DUAL UNION ALL
选择 'B', 0, 2, 1 FROM DUAL UNION ALL
选择 'C', 0, 3, 1 FROM DUAL UNION ALL
选择 'D', 1, 4, 1 FROM DUAL UNION ALL
选择 'E', 1, 5, 1 FROM DUAL UNION ALL
选择 'F', 1, 6, 1 FROM DUAL UNION ALL
选择 'G', 0, 7, 1 FROM DUAL UNION ALL
选择 'H', 1, 8, 1 FROM DUAL UNION ALL
选择 'I', 1, 1, 2 FROM DUAL UNION ALL
选择 'J', 0, 2, 2 FROM DUAL UNION ALL
选择 'K', 1, 3, 2 FROM DUAL UNION ALL
选择 'L', 1, 4, 2 FROM DUAL;

输出:

列1 指示器 序列 类别 结果1
A 1 1 1 A
B 0 2 1 B
C 0 3 1 C
D 1 4 1 A+B+C+D
E 1 5 1 A+B+C+D+E
F 1 6 1 A+B+C+D+E+F
G 0 7 1 G
H 1 8 1 A+B+C+D+E+F+G+H
I 1 1 2 I
J 0 2 2 J
K 1 3 2 I+J+K
L 1 4 2 I+J+K+L
英文:

You can use a MODEL clause:

SELECT column1,
       indicator,
       seqnce,
       category,
       CASE indicator
       WHEN 0
       THEN column1
       ELSE res
       END AS res1
FROM   dmy_tbl
MODEL
  PARTITION BY (category)
  DIMENSION BY (seqnce)
  MEASURES (
    column1,
    indicator,
    CAST(NULL AS VARCHAR2(4000)) AS res
  )  
  RULES (
    res[1] = column1[1],
    res[seqnce&gt;1] = res[cv()-1] || &#39;+&#39; || column1[cv()]
  );

Which, for the sample data:

CREATE TABLE dmy_tbl (column1, indicator, seqnce, category) AS
SELECT &#39;A&#39;, 1, 1, 1 FROM DUAL UNION ALL
SELECT &#39;B&#39;, 0, 2, 1 FROM DUAL UNION ALL
SELECT &#39;C&#39;, 0, 3, 1 FROM DUAL UNION ALL
SELECT &#39;D&#39;, 1, 4, 1 FROM DUAL UNION ALL
SELECT &#39;E&#39;, 1, 5, 1 FROM DUAL UNION ALL
SELECT &#39;F&#39;, 1, 6, 1 FROM DUAL UNION ALL
SELECT &#39;G&#39;, 0, 7, 1 FROM DUAL UNION ALL
SELECT &#39;H&#39;, 1, 8, 1 FROM DUAL UNION ALL
SELECT &#39;I&#39;, 1, 1, 2 FROM DUAL UNION ALL
SELECT &#39;J&#39;, 0, 2, 2 FROM DUAL UNION ALL
SELECT &#39;K&#39;, 1, 3, 2 FROM DUAL UNION ALL
SELECT &#39;L&#39;, 1, 4, 2 FROM DUAL;

Outputs:

COLUMN1 INDICATOR SEQNCE CATEGORY RES1
A 1 1 1 A
B 0 2 1 B
C 0 3 1 C
D 1 4 1 A+B+C+D
E 1 5 1 A+B+C+D+E
F 1 6 1 A+B+C+D+E+F
G 0 7 1 G
H 1 8 1 A+B+C+D+E+F+G+H
I 1 1 2 I
J 0 2 2 J
K 1 3 2 I+J+K
L 1 4 2 I+J+K+L

fiddle

答案2

得分: 0

从Oracle 12开始,您可以使用MATCH_RECOGNIZELISTAGG

SELECT MAX(CASE rn WHEN 1 THEN column1 END) AS column1,
       MAX(CASE rn WHEN 1 THEN indicator END) AS indicator,
       MAX(CASE rn WHEN 1 THEN seqnce END) AS seqnce,
       category,
       LISTAGG(column1, '&#39;+&#39;) WITHIN GROUP (ORDER BY column1) AS res1
FROM   dmy_tbl
MATCH_RECOGNIZE(
  PARTITION BY category
  ORDER BY seqnce DESC
  MEASURES
    COUNT(*) AS rn,
    MATCH_NUMBER() AS mn
  ALL ROWS PER MATCH
  AFTER MATCH SKIP TO NEXT ROW
  PATTERN ( zero | one any_row* )
  DEFINE
    zero AS indicator = 0,
    one  AS indicator = 1
)
GROUP BY category, mn
ORDER BY category, seqnce;

对于示例数据:

CREATE TABLE dmy_tbl (column1, indicator, seqnce, category) AS
SELECT '&#39;A&#39;', 1, 1, 1 FROM DUAL UNION ALL
SELECT '&#39;B&#39;', 0, 2, 1 FROM DUAL UNION ALL
SELECT '&#39;C&#39;', 0, 3, 1 FROM DUAL UNION ALL
SELECT '&#39;D&#39;', 1, 4, 1 FROM DUAL UNION ALL
SELECT '&#39;E&#39;', 1, 5, 1 FROM DUAL UNION ALL
SELECT '&#39;F&#39;', 1, 6, 1 FROM DUAL UNION ALL
SELECT '&#39;G&#39;', 0, 7, 1 FROM DUAL UNION ALL
SELECT '&#39;H&#39;', 1, 8, 1 FROM DUAL UNION ALL
SELECT '&#39;I&#39;', 1, 1, 2 FROM DUAL UNION ALL
SELECT '&#39;J&#39;', 0, 2, 2 FROM DUAL UNION ALL
SELECT '&#39;K&#39;', 1, 3, 2 FROM DUAL UNION ALL
SELECT '&#39;L&#39;', 1, 4, 2 FROM DUAL;

输出:

COLUMN1 INDICATOR SEQNCE CATEGORY RES1
A 1 1 1 A
B 0 2 1 B
C 0 3 1 C
D 1 4 1 A+B+C+D
E 1 5 1 A+B+C+D+E
F 1 6 1 A+B+C+D+E+F
G 0 7 1 G
H 1 8 1 A+B+C+D+E+F+G+H
I 1 1 2 I
J 0 2 2 J
K 1 3 2 I+J+K
L 1 4 2 I+J+K+L

fiddle

英文:

From Oracle 12, you can use MATCH_RECOGNIZE and LISTAGG:

SELECT MAX(CASE rn WHEN 1 THEN column1 END) AS column1,
       MAX(CASE rn WHEN 1 THEN indicator END) AS indicator,
       MAX(CASE rn WHEN 1 THEN seqnce END) AS seqnce,
       category,
       LISTAGG(column1, &#39;+&#39;) WITHIN GROUP (ORDER BY column1) AS res1
FROM   dmy_tbl
MATCH_RECOGNIZE(
  PARTITION BY category
  ORDER BY seqnce DESC
  MEASURES
    COUNT(*) AS rn,
    MATCH_NUMBER() AS mn
  ALL ROWS PER MATCH
  AFTER MATCH SKIP TO NEXT ROW
  PATTERN ( zero | one any_row* )
  DEFINE
    zero AS indicator = 0,
    one  AS indicator = 1
)
GROUP BY category, mn
ORDER BY category, seqnce;

Which, for the sample data:

CREATE TABLE dmy_tbl (column1, indicator, seqnce, category) AS
SELECT &#39;A&#39;, 1, 1, 1 FROM DUAL UNION ALL
SELECT &#39;B&#39;, 0, 2, 1 FROM DUAL UNION ALL
SELECT &#39;C&#39;, 0, 3, 1 FROM DUAL UNION ALL
SELECT &#39;D&#39;, 1, 4, 1 FROM DUAL UNION ALL
SELECT &#39;E&#39;, 1, 5, 1 FROM DUAL UNION ALL
SELECT &#39;F&#39;, 1, 6, 1 FROM DUAL UNION ALL
SELECT &#39;G&#39;, 0, 7, 1 FROM DUAL UNION ALL
SELECT &#39;H&#39;, 1, 8, 1 FROM DUAL UNION ALL
SELECT &#39;I&#39;, 1, 1, 2 FROM DUAL UNION ALL
SELECT &#39;J&#39;, 0, 2, 2 FROM DUAL UNION ALL
SELECT &#39;K&#39;, 1, 3, 2 FROM DUAL UNION ALL
SELECT &#39;L&#39;, 1, 4, 2 FROM DUAL;

Outputs:

COLUMN1 INDICATOR SEQNCE CATEGORY RES1
A 1 1 1 A
B 0 2 1 B
C 0 3 1 C
D 1 4 1 A+B+C+D
E 1 5 1 A+B+C+D+E
F 1 6 1 A+B+C+D+E+F
G 0 7 1 G
H 1 8 1 A+B+C+D+E+F+G+H
I 1 1 2 I
J 0 2 2 J
K 1 3 2 I+J+K
L 1 4 2 I+J+K+L

fiddle

答案3

得分: 0

如果您不关心是否涉及PL/SQL,一个简单的函数可能会完成任务。

SQL> CREATE OR REPLACE FUNCTION f_res (par_category IN NUMBER, par_seqnce NUMBER)
  2     RETURN VARCHAR2
  3  IS
  4     l_row   test%ROWTYPE;
  5     retval  VARCHAR2 (30);
  6  BEGIN
  7     SELECT *
  8       INTO l_row
  9       FROM test
 10      WHERE     category = par_category
 11            AND seqnce = par_seqnce;
 12
 13     IF l_row.flg = 0
 14     THEN
 15        retval := l_row.column1;
 16     ELSE
 17        SELECT LISTAGG (column1, '+') WITHIN GROUP (ORDER BY seqnce)
 18          INTO retval
 19          FROM test
 20         WHERE     category = par_category
 21               AND seqnce <= par_seqnce;
 22     END IF;
 23
 24     RETURN retval;
 25  END;
 26  /

函数已创建。

测试:

SQL>   SELECT t.*, f_res (t.category, t.seqnce) res1
  2      FROM test t
  3  ORDER BY t.category, t.seqnce;

C     SEQNCE        FLG   CATEGORY RES1
- ---------- ---------- ---------- ------------------------------
A          1          1          1 A
B          2          0          1 B
C          3          0          1 C
D          4          1          1 A+B+C+D
E          5          1          1 A+B+C+D+E
F          6          1          1 A+B+C+D+E+F
G          7          0          1 G
H          8          1          1 A+B+C+D+E+F+G+H
I          1          1          2 I
J          2          0          2 J
K          3          1          2 I+J+K
L          4          1          2 I+J+K+L

12 rows selected.

SQL>
英文:

If you don't care whether PL/SQL is involved, a simple function might do the job.

SQL&gt; CREATE OR REPLACE FUNCTION f_res (par_category IN NUMBER, par_seqnce NUMBER)
2     RETURN VARCHAR2
3  IS
4     l_row   test%ROWTYPE;
5     retval  VARCHAR2 (30);
6  BEGIN
7     SELECT *
8       INTO l_row
9       FROM test
10      WHERE     category = par_category
11            AND seqnce = par_seqnce;
12
13     IF l_row.flg = 0
14     THEN
15        retval := l_row.column1;
16     ELSE
17        SELECT LISTAGG (column1, &#39;+&#39;) WITHIN GROUP (ORDER BY seqnce)
18          INTO retval
19          FROM test
20         WHERE     category = par_category
21               AND seqnce &lt;= par_seqnce;
22     END IF;
23
24     RETURN retval;
25  END;
26  /
Function created.

Testing:

SQL&gt;   SELECT t.*, f_res (t.category, t.seqnce) res1
2      FROM test t
3  ORDER BY t.category, t.seqnce;
C     SEQNCE        FLG   CATEGORY RES1
- ---------- ---------- ---------- ------------------------------
A          1          1          1 A
B          2          0          1 B
C          3          0          1 C
D          4          1          1 A+B+C+D
E          5          1          1 A+B+C+D+E
F          6          1          1 A+B+C+D+E+F
G          7          0          1 G
H          8          1          1 A+B+C+D+E+F+G+H
I          1          1          2 I
J          2          0          2 J
K          3          1          2 I+J+K
L          4          1          2 I+J+K+L
12 rows selected.
SQL&gt;

huangapple
  • 本文由 发表于 2023年6月27日 18:23:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76563909.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定