一条记录上面查询记录的SQL语句

问题描述 投票:0回答:4

我有一个包含 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 万条记录。

想法?

sql oracle lag
4个回答
0
投票

选择两行并用正则表达式丢弃错误的行

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”中的内容。您可能还必须丢弃正则表达式中的其他值。


0
投票

不需要连接或子查询。借助 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
约翰史密斯
简·史密斯
小雅各布·约翰·史密斯

小提琴


0
投票

您可以使用窗口函数检查两行的值

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
小雅各布·约翰·史密斯

小提琴


0
投票

我知道您想要列中每次出现的字符串

'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 选项在查找实际员工姓名时跳过它们。

© www.soinside.com 2019 - 2024. All rights reserved.