如何使用单个列值的多个子字符串在 SQL table 中 select 行?
How can I select rows in an SQL table by using multiple substrings of a single column value?
我正在使用 Oracle SQL Developer 查询案例数据库,我需要使用三个不同的标识符来 select 每个案例的正确行;然而,我的问题是两个标识符包含在同一个文本字符串中,我不知道如何解析它们以在查询中使用。
在下面的table中,我需要使用的标识符是:
- ID-1,“案例”列中的字符 3–6(例如,“1001”),
- ID-2,“案例”列中的字符 8–9(例如,“01”)出现时(如果它们不出现,则被视为“00”),并且
- ID-3,“序列”列中的值(例如,“672”)。
来源Table
Case
Sequence
Value 1
Value 2
AA1001
672
73
195
AA1001
711
73
185
AA1001-01
680
73
185
AA1001-02
685
72
185
AA1001-02
699
72
182
AB1002
676
51
36
AB1002-01
701
48
39
AB1002-01
719
48
35
AB1002-02
707
51
38
AA1003
655
122
416
AA1003
683
113
416
我想 return 每个唯一的 ID-1 一行,这样 第一个 ID-2 的最大值是 selected,然后然后选择该子集中ID-3 的最大值;因此,查询应该 return 只有上面 table 中的以下三行。
结果Table
Case
Sequence
Value 1
Value 2
AA1001-02
699
72
182
AB1002-02
707
51
38
AA1003
683
113
416
我已经尝试使用以下方法获取 ID-2 的最大值,但它仅 returns ID-2 等于“02”的行。
SELECT *
FROM table
WHERE SUBSTR(Case,3,4) in ('1001','1002','1003')
and SUBSTR(Case,8,2) = (SELECT MAX(SUBSTR(Case,8,2))
FROM table
WHERE SUBSTR(Case,3,4) in ('1001','1002','1003'))
(最简单的答案可能只是为 ID-2 添加一列;但是,源数据库是严格只读的,因此我无法进行此类更改。)
您可以使用 ROW_NUMBER()
分析函数并找到 SUBSTR
到 partition/order 的方法:
SELECT *
FROM (
SELECT t.*,
ROW_NUMBER() OVER (
PARTITION BY
SUBSTR(Case, 3, 4)
ORDER BY
COALESCE(SUBSTR(Case, 8, 2), '00') DESC,
Sequence DESC
) AS rn
FROM table_name t
)
WHERE rn = 1;
其中,对于您的示例数据:
CREATE TABLE table_name (Case, Sequence, Value1, Value2 ) AS
SELECT 'AA1001', 672, 73, 195 FROM DUAL UNION ALL
SELECT 'AA1001', 711, 73, 185 FROM DUAL UNION ALL
SELECT 'AA1001-01', 680, 73, 185 FROM DUAL UNION ALL
SELECT 'AA1001-02', 685, 72, 185 FROM DUAL UNION ALL
SELECT 'AA1001-02', 699, 72, 182 FROM DUAL UNION ALL
SELECT 'AB1002', 676, 51, 36 FROM DUAL UNION ALL
SELECT 'AB1002-01', 701, 48, 39 FROM DUAL UNION ALL
SELECT 'AB1002-01', 719, 48, 35 FROM DUAL UNION ALL
SELECT 'AB1002-02', 707, 51, 38 FROM DUAL UNION ALL
SELECT 'AA1003', 655, 122, 416 FROM DUAL UNION ALL
SELECT 'AA1003', 683, 113, 416 FROM DUAL;
输出:
CASE
SEQUENCE
VALUE1
VALUE2
RN
AA1001-02
699
72
182
1
AB1002-02
707
51
38
1
AA1003
683
113
416
1
db<>fiddle here
在 Oracle 12.1 及更高版本中,您可以使用 match_recognize
子句:
select case, sequence, value1, value2
from (
select t.*, substr(case, 3, 4) as id_1, substr(case, 8, 2) as id_2
from table_name t
)
match_recognize(
partition by id_1
order by id_2 desc nulls last, sequence desc nulls last
all rows per match
pattern (^ x)
define x as null is null
);
CASE SEQUENCE VALUE1 VALUE2
--------- ---------- ---------- ----------
AA1001-02 699 72 182
AB1002-02 707 51 38
AA1003 683 113 416
我正在使用 Oracle SQL Developer 查询案例数据库,我需要使用三个不同的标识符来 select 每个案例的正确行;然而,我的问题是两个标识符包含在同一个文本字符串中,我不知道如何解析它们以在查询中使用。
在下面的table中,我需要使用的标识符是:
- ID-1,“案例”列中的字符 3–6(例如,“1001”),
- ID-2,“案例”列中的字符 8–9(例如,“01”)出现时(如果它们不出现,则被视为“00”),并且
- ID-3,“序列”列中的值(例如,“672”)。
来源Table
Case | Sequence | Value 1 | Value 2 |
---|---|---|---|
AA1001 | 672 | 73 | 195 |
AA1001 | 711 | 73 | 185 |
AA1001-01 | 680 | 73 | 185 |
AA1001-02 | 685 | 72 | 185 |
AA1001-02 | 699 | 72 | 182 |
AB1002 | 676 | 51 | 36 |
AB1002-01 | 701 | 48 | 39 |
AB1002-01 | 719 | 48 | 35 |
AB1002-02 | 707 | 51 | 38 |
AA1003 | 655 | 122 | 416 |
AA1003 | 683 | 113 | 416 |
我想 return 每个唯一的 ID-1 一行,这样 第一个 ID-2 的最大值是 selected,然后然后选择该子集中ID-3 的最大值;因此,查询应该 return 只有上面 table 中的以下三行。
结果Table
Case | Sequence | Value 1 | Value 2 |
---|---|---|---|
AA1001-02 | 699 | 72 | 182 |
AB1002-02 | 707 | 51 | 38 |
AA1003 | 683 | 113 | 416 |
我已经尝试使用以下方法获取 ID-2 的最大值,但它仅 returns ID-2 等于“02”的行。
SELECT *
FROM table
WHERE SUBSTR(Case,3,4) in ('1001','1002','1003')
and SUBSTR(Case,8,2) = (SELECT MAX(SUBSTR(Case,8,2))
FROM table
WHERE SUBSTR(Case,3,4) in ('1001','1002','1003'))
(最简单的答案可能只是为 ID-2 添加一列;但是,源数据库是严格只读的,因此我无法进行此类更改。)
您可以使用 ROW_NUMBER()
分析函数并找到 SUBSTR
到 partition/order 的方法:
SELECT *
FROM (
SELECT t.*,
ROW_NUMBER() OVER (
PARTITION BY
SUBSTR(Case, 3, 4)
ORDER BY
COALESCE(SUBSTR(Case, 8, 2), '00') DESC,
Sequence DESC
) AS rn
FROM table_name t
)
WHERE rn = 1;
其中,对于您的示例数据:
CREATE TABLE table_name (Case, Sequence, Value1, Value2 ) AS
SELECT 'AA1001', 672, 73, 195 FROM DUAL UNION ALL
SELECT 'AA1001', 711, 73, 185 FROM DUAL UNION ALL
SELECT 'AA1001-01', 680, 73, 185 FROM DUAL UNION ALL
SELECT 'AA1001-02', 685, 72, 185 FROM DUAL UNION ALL
SELECT 'AA1001-02', 699, 72, 182 FROM DUAL UNION ALL
SELECT 'AB1002', 676, 51, 36 FROM DUAL UNION ALL
SELECT 'AB1002-01', 701, 48, 39 FROM DUAL UNION ALL
SELECT 'AB1002-01', 719, 48, 35 FROM DUAL UNION ALL
SELECT 'AB1002-02', 707, 51, 38 FROM DUAL UNION ALL
SELECT 'AA1003', 655, 122, 416 FROM DUAL UNION ALL
SELECT 'AA1003', 683, 113, 416 FROM DUAL;
输出:
CASE SEQUENCE VALUE1 VALUE2 RN AA1001-02 699 72 182 1 AB1002-02 707 51 38 1 AA1003 683 113 416 1
db<>fiddle here
在 Oracle 12.1 及更高版本中,您可以使用 match_recognize
子句:
select case, sequence, value1, value2
from (
select t.*, substr(case, 3, 4) as id_1, substr(case, 8, 2) as id_2
from table_name t
)
match_recognize(
partition by id_1
order by id_2 desc nulls last, sequence desc nulls last
all rows per match
pattern (^ x)
define x as null is null
);
CASE SEQUENCE VALUE1 VALUE2
--------- ---------- ---------- ----------
AA1001-02 699 72 182
AB1002-02 707 51 38
AA1003 683 113 416