我有一个包含 600 万条记录的数据库,这些记录是从 PDF 会计凭证中提取的。
在数据库中,我在A列中有一条记录,其值为:“员工姓名”。 B 列中的递增索引从 1 到 600 万。
值“员工姓名”上方的记录有时是员工的姓名,带有数字。
有时是null,有时是数字。在任何一种情况下,员工姓名都列在上面的记录中。
例子:
A | 乙 |
---|---|
“约翰·史密斯 12345” | 19 |
“员工姓名” | 20 |
“别的” | 21 |
“别的” | 22 |
《简史密斯56789》 | 23 |
“空” | 24 |
“员工姓名” | 25 |
“别的” | 26 |
“别的” | 27 |
“小雅各布·约翰·史密斯” | 28 |
“98765” | 29 |
“员工姓名” | 30 |
“别的” | 31 |
我需要得到员工的姓名。过滤掉数字可能是个不错的奖励,但现在我很高兴至少能得到名字。
SELECT DISTINCT A
FROM PAYROLL_RECORDS
WHERE B IN (SELECT (B - 1) FROM PAYROLL_RECORDS
WHERE A = 'Employee Name')
ORDER BY A;
如果名字总是在它上面的行,这将完美地工作。
我需要一个
SELECT
语句,它可能会抓住顶部的两行,并检查它是否在 A 列中有字符(而不是数字或 NULL)。
我需要一份包含所有不同员工姓名的列表,完整扫描所有 600 万条记录。
想法?
选择两行并用正则表达式丢弃错误的行
SELECT DISTINCT A FROM PAYROLL_RECORDS
WHERE
(B IN (SELECT (B - 1) FROM PAYROLL_RECORDS WHERE A = 'Employee Name') OR
B IN (SELECT (B - 2) FROM PAYROLL_RECORDS WHERE A = 'Employee Name')) AND
NOT regexp_like(A, '^(\d+|null)$')
ORDER BY A;
成功也取决于“Something Else”中的内容。您可能还必须丢弃正则表达式中的其他值。
不需要连接或子查询。借助 where 子句,您可以从 A 列中删除空值和数值,然后
lag()over()
窗口函数将帮助您获取每个“员工姓名”的前面的值。第一行永远是null
查询:
select distinct case when A='Employee Name' then lag(regexp_replace(A, '[0-9]', ''))over(order by B) end as A from PAYROLL_RECORDS
where A is not null and VALIDATE_CONVERSION(A AS NUMBER) <> 1
输出:
A |
---|
空 |
约翰史密斯 |
简·史密斯 |
小雅各布·约翰·史密斯 |
如果你想删除具有空值的第一行,那么:
查询:
select A from
(select distinct case when A='Employee Name' then lag(regexp_replace(A, '[0-9]', ''))over(order by B) end as A from PAYROLL_RECORDS
where A is not null and VALIDATE_CONVERSION(A AS NUMBER) <> 1 )
t where A is not null
输出:
A |
---|
约翰史密斯 |
简·史密斯 |
小雅各布·约翰·史密斯 |
您可以使用窗口函数检查两行的值
LEAD
WITH CTE AS
(SELECT
"A",
LEAD("A") OVER(ORDER BY "B") row1
,
LEAD("A",2) OVER(ORDER BY "B") row2
FROM
PAYROLL_RECORDS)
SELECT "A" FROM CTE
WHERE (row1 = 'Employee Name' OR row2 = 'Employee Name')
AND (NOT REGEXP_LIKE("A", '^[[:digit:]]+$'))
A |
---|
约翰史密斯 12345" |
简·史密斯 56789 |
小雅各布·约翰·史密斯 |
我知道您想要列中每次出现的字符串
'Employee Name'
的“先前”非空值和非数字值。
我会推荐
lag
带有条件表达式和 ignore nulls
选项:
select distinct employee_name
from (
select p.*,
lag(case when not regexp_like(a, '^\d+$') then a end)
ignore nulls
over(order by b) employee_name
from payroll_records p
) p
where a = 'Employee Name'
诀窍是让
lag()
中的表达式将不需要的值转换为 null
值,以便 ignore null
s 选项在查找实际员工姓名时跳过它们。