[英]How can I select rows in an SQL table by using multiple substrings of a single column value?
I am using Oracle SQL Developer to query a database of cases, and I need to use three different identifiers to select the correct row for each case;我正在使用 Oracle SQL Developer 查询案例数据库,我需要使用三个不同的标识符为每个案例选择正确的行; however, my problem is that two of the identifiers are contained in the same text string, and I can't figure out how to parse them to use in the query.
但是,我的问题是两个标识符包含在同一个文本字符串中,我不知道如何解析它们以在查询中使用。
In the following table, the identifiers I need to use are:在下表中,我需要使用的标识符是:
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 ![]() |
I want to return one row for each unique ID-1, such that first the greatest value for ID-2 is selected, and then the greatest value for ID-3 in that subset is chosen;我想为每个唯一的 ID-1 返回一行,这样首先选择 ID-2 的最大值,然后选择该子集中ID-3 的最大值; so, the query should return only the following three rows from the table above.
因此,查询应仅返回上表中的以下三行。
Case![]() |
Sequence![]() |
Value 1![]() |
Value 2![]() |
---|---|---|---|
AA1001-02 ![]() |
699 ![]() |
72 ![]() |
182 ![]() |
AB1002-02 ![]() |
707 ![]() |
51 ![]() |
38 ![]() |
AA1003 ![]() |
683 ![]() |
113 ![]() |
416 ![]() |
I've tried taking the maximum for ID-2 using the following, but it only returns the rows where ID-2 equals "02".我尝试使用以下方法为 ID-2 取最大值,但它只返回 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'))
(The easiest answer is probably just to add a column for ID-2; however, the source database is strictly read-only, so I can't make that sort of change.) (最简单的答案可能只是为 ID-2 添加一列;但是,源数据库是严格只读的,因此我无法进行此类更改。)
In Oracle 12.1 and higher, you can use the match_recognize
clause:在 Oracle 12.1 及更高版本中,您可以使用
match_recognize
子句:
select case, sequence, value1, value2
from (
select t.*, substr(case, 3, 4) as id_1, substr(case, 8, 9) 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
You can use the ROW_NUMBER()
analytic function and find the SUBSTR
ings to partition/order by:您可以使用
ROW_NUMBER()
分析函数并通过以下方式找到要分区/排序的SUBSTR
ings:
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;
Which, for your sample data:其中,对于您的示例数据:
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;
Outputs:输出:
CASE 案件
SEQUENCE 序列
VALUE1 VALUE1
VALUE2 VALUE2
RN 注册护士
AA1001-02 AA1001-02
699 699
72 72
182 182
1 1
AB1002-02 AB1002-02
707 707
51 51
38 38
1 1
AA1003 AA1003
683 683
113 113
416 416
1 1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.