Oracle SQL:使用 WHERE LIKE 但针对特定的整个单词 / REGEXP_LIKE
Oracle SQL: Using WHERE LIKE but for specific whole words / REGEXP_LIKE
我有 table 的发票,其中成本标识符以特定方式保存,并不总是标准的,如下所示:
ID | SYMBOL | COST_IDS
---+--------+-------------------
1 | FV01 | '1076219, 1081419'
2 | FV02 | '107621,123421'
3 | FV03 | '111521; 107621'
我想查找特定费用标识符的发票。
成本的结构是(4 或更多位数)+(2年位数)
在测试用例中:107621
,所需的输出将是 ID:2 and 3
。
SELECT * FROM INVOICES WHERE COST_IDS like '%107621%'
是错误的做法。
我发现我需要使用 REGEXP_LIKE
并且我正在努力解决它。我知道我需要准确地找到整个世界,但不一定要从头开始。
谁能帮帮我?
编辑:这似乎在大多数情况下都有效,但在字符串结尾处失败:
SELECT *
FROM INVOICES
WHERE REGEXP_LIKE(COST_IDS, '[^|\s|,|;]107621[$|\s|,|;]')
还有没有办法标记'non-digit'字符而不是专门写\s|,|;
?
为什么 $
不起作用?
您可以使用\D
来匹配一个非数字:
SELECT *
FROM INVOICES
WHERE REGEXP_LIKE(COST_IDS, '(^|\D)107621(\D|$)')
其中,对于示例数据:
CREATE TABLE invoices (ID, SYMBOL, COST_IDS) AS
SELECT 1, 'FV01', '1076219, 1081419' FROM DUAL UNION ALL
SELECT 2, 'FV02', '107621,123421' FROM DUAL UNION ALL
SELECT 3, 'FV03', '111521; 107621' FROM DUAL;
输出:
ID
SYMBOL
COST_IDS
2
FV02
107621,123421
3
FV03
111521; 107621
db<>fiddle here
您的正则表达式不能正常工作:
[^|\s|,|;]
匹配 而不是 |
或 \
或 s
或 |
的单个字符] 或 ,
或 |
或 ;
[$|\s|,|;]
匹配 $
或 |
或 \
或 s
或 |
或 [=18] 中的单个字符=] 或 |
或 ;
如果要匹配字符串开头或白色 space 字符或逗号或分号,则需要正则表达式 (^|\s|[,;])
.
同样,如果你想匹配字符串结尾或白色 space 字符或逗号或分号,那么你需要正则表达式 ($|\s|[,;])
.
您可以使用以下 SQL Select 语句,考虑到 cost_ids
有两个单独的部分,或者假设每个 cost_ids
值甚至只有一种类型的分隔符如果有更多部分
WITH inv AS
(
SELECT id, REGEXP_SUBSTR(cost_ids,'[[:punct:]]+') AS symbol2, cost_ids
FROM invoices
)
SELECT DISTINCT id
FROM inv
WHERE REGEXP_SUBSTR(cost_ids,'[^'''||symbol2||''' ]+',1,level) = '107621'
CONNECT BY level <= REGEXP_COUNT(cost_ids,symbol2) + 1
AND PRIOR SYS_GUID() IS NOT NULL
AND PRIOR id = id
其中分隔符最初通过使用 [[:punct:]]
posix 的名称 symbol2
确定,用于提取标点符号。
我有 table 的发票,其中成本标识符以特定方式保存,并不总是标准的,如下所示:
ID | SYMBOL | COST_IDS
---+--------+-------------------
1 | FV01 | '1076219, 1081419'
2 | FV02 | '107621,123421'
3 | FV03 | '111521; 107621'
我想查找特定费用标识符的发票。
成本的结构是(4 或更多位数)+(2年位数)
在测试用例中:107621
,所需的输出将是 ID:2 and 3
。
SELECT * FROM INVOICES WHERE COST_IDS like '%107621%'
是错误的做法。
我发现我需要使用 REGEXP_LIKE
并且我正在努力解决它。我知道我需要准确地找到整个世界,但不一定要从头开始。
谁能帮帮我?
编辑:这似乎在大多数情况下都有效,但在字符串结尾处失败:
SELECT *
FROM INVOICES
WHERE REGEXP_LIKE(COST_IDS, '[^|\s|,|;]107621[$|\s|,|;]')
还有没有办法标记'non-digit'字符而不是专门写\s|,|;
?
为什么 $
不起作用?
您可以使用\D
来匹配一个非数字:
SELECT *
FROM INVOICES
WHERE REGEXP_LIKE(COST_IDS, '(^|\D)107621(\D|$)')
其中,对于示例数据:
CREATE TABLE invoices (ID, SYMBOL, COST_IDS) AS
SELECT 1, 'FV01', '1076219, 1081419' FROM DUAL UNION ALL
SELECT 2, 'FV02', '107621,123421' FROM DUAL UNION ALL
SELECT 3, 'FV03', '111521; 107621' FROM DUAL;
输出:
ID SYMBOL COST_IDS 2 FV02 107621,123421 3 FV03 111521; 107621
db<>fiddle here
您的正则表达式不能正常工作:
[^|\s|,|;]
匹配 而不是|
或\
或s
或|
的单个字符] 或,
或|
或;
[$|\s|,|;]
匹配$
或|
或\
或s
或|
或 [=18] 中的单个字符=] 或|
或;
如果要匹配字符串开头或白色 space 字符或逗号或分号,则需要正则表达式 (^|\s|[,;])
.
同样,如果你想匹配字符串结尾或白色 space 字符或逗号或分号,那么你需要正则表达式 ($|\s|[,;])
.
您可以使用以下 SQL Select 语句,考虑到 cost_ids
有两个单独的部分,或者假设每个 cost_ids
值甚至只有一种类型的分隔符如果有更多部分
WITH inv AS
(
SELECT id, REGEXP_SUBSTR(cost_ids,'[[:punct:]]+') AS symbol2, cost_ids
FROM invoices
)
SELECT DISTINCT id
FROM inv
WHERE REGEXP_SUBSTR(cost_ids,'[^'''||symbol2||''' ]+',1,level) = '107621'
CONNECT BY level <= REGEXP_COUNT(cost_ids,symbol2) + 1
AND PRIOR SYS_GUID() IS NOT NULL
AND PRIOR id = id
其中分隔符最初通过使用 [[:punct:]]
posix 的名称 symbol2
确定,用于提取标点符号。