Oracle 潜在客户查询

Posted

技术标签:

【中文标题】Oracle 潜在客户查询【英文标题】:Oracle lead query 【发布时间】:2015-11-12 16:43:26 【问题描述】:

我有一个如下查询,其中内部查询返回以下结果集。我需要修改查询,以便在它返回空值的最后一行中,我希望返回第一个 emp_id。基本上,试图在最后一行的下一个 empid 中获取第一行中的 empid。我希望这是有道理的。任何想法表示赞赏。

注意:更新了查询,当我将案例逻辑添加到最后一列时,我收到错误 ORA-01467:排序键太长

SELECT *  FROM (     SELECT emp_id
                           , lead(emp_id) OVER ( ORDER BY join_dt DESC, emp_id desc ) AS next_emp_id
                           , lead(title) OVER ( ORDER BY join_dt DESC, emp_id desc ) AS next_title
                           , lead(join_dt) OVER ( ORDER BY join_dt DESC, emp_id desc ) AS next_join_dt  
                           ,lead(url_keyword) OVER ( ORDER BY publish_dt DESC, art_id desc ) AS next_url_keyword


                      FROM (
                            SELECT DISTINCT eca.emp_id, a.title, max(esa.join_dt) as join_dt,REGEXP_SUBSTR(REGEXP_REPLACE(LOWER(a.empword), '[^a-z0-9]+', '-'), '([a-z0-9]+-?)0,5([a-z0-9]+)') as url_keyword
                              FROM  emp_groups eca,  emp a, emp_assignment esa
                             WHERE eca.emp_group_id = 9
                               AND eca.emp_id = a.emp_id
                               AND a.emp_id = esa.emp_id
                             GROUP BY eca.emp_id, a.title,REGEXP_SUBSTR(REGEXP_REPLACE(LOWER(a.empword), '[^a-z0-9]+', '-'), '([a-z0-9]+-?)0,5([a-z0-9]+)')
                             UNION ALL
                            SELECT DISTINCT eca.emp_id, a.title, max(esa.join_dt) as join_dt, REGEXP_SUBSTR(REGEXP_REPLACE(LOWER(a.empword), '[^a-z0-9]+', '-'), '([a-z0-9]+-?)0,5([a-z0-9]+)') as url_keyword 
                              FROM  emp_groups eca,  emp_archive a,  emp_assign_archive esa
                             WHERE eca.emp_group_id = 9
                               AND eca.emp_id = a.emp_id
                               AND a.emp_id = esa.emp_id
                             GROUP BY eca.emp_id, a.title,, REGEXP_SUBSTR(REGEXP_REPLACE(LOWER(a.empword), '[^a-z0-9]+', '-'), '([a-z0-9]+-?)0,5([a-z0-9]+)')
                             UNION ALL 
                            SELECT DISTINCT eca.emp_id, a.title, max(esa.join_dt) as join_dt ,REGEXP_SUBSTR(REGEXP_REPLACE(LOWER(a.empword), '[^a-z0-9]+', '-'), '([a-z0-9]+-?)0,5([a-z0-9]+)') as url_keyword
                              FROM  emp_groups eca,  emp_archive a,  emp_assignment esa
                             WHERE eca.emp_group_id = 9
                               AND eca.emp_id = a.emp_id
                               AND a.emp_id = esa.emp_id
                             GROUP BY eca.emp_id, a.title,, REGEXP_SUBSTR(REGEXP_REPLACE(LOWER(a.empword), '[^a-z0-9]+', '-'), '([a-z0-9]+-?)0,5([a-z0-9]+)')
                           )
                  )
            WHERE emp_id = 6046935 

 empid  nextempid   title               date
6235396 6239577 radio engineer         8/5/2015 
6239577 6219531 radar engineer         7/16/2015 
6219531 6083501 software engineer      7/8/2015 
6083501 6141972 Project manager        6/24/2015
6141972 6163194 QA engineer            6/1/2015
6163194 6142464 technician             5/18/2015
6142464 6046935 teacher                4/23/2015
6046935 (null)  (null)                 (null)

需要的结果集

    empid   nextempid   nexttitle          nextdate
    6235396 6239577 radio engineer         8/5/2015 
    6239577 6219531 radar engineer         7/16/2015 
    6219531 6083501 software engineer      7/8/2015 
    6083501 6141972 Project manager        6/24/2015
    6141972 6163194 QA engineer            6/1/2015
    6163194 6142464 technician             5/18/2015
    6142464 6046935 teacher                4/23/2015
    6046935 6235396 doctor                 9/5/2015

【问题讨论】:

empid = 6235396 的 join_dt 真的是 2015 年 5 月 5 日吗?因为如果将 empid = 6239577 作为下一行,它的日期不应该大于 2015 年 8 月 5 日吗? 是的,抱歉打错了,已更新。谢谢 您不需要子查询中的差异,顺便说一句!你已经在分组了。 我看了那篇文章,不太清楚如何更改列的值? 一种方法是更改​​您的查询以找到每个 emp_id 将其加入每个查询中的其他表之前的最大 join_date。 【参考方案1】:

您可以使用first_value() 分析函数来查找该组行的第一个值,然后在下一行的值为空时使用该值。

with sample_data as (select 6235396 emp_id, 'doctor' title, to_date('9/05/2015', 'mm/dd/yyyy') join_dt from dual union all
                     select 6239577 emp_id, 'radio engineer' title, to_date('08/05/2015', 'mm/dd/yyyy') join_dt from dual union all
                     select 6219531 emp_id, 'radar engineer' title, to_date('07/16/2015', 'mm/dd/yyyy') join_dt from dual union all
                     select 6083501 emp_id, 'software engineer' title, to_date('07/08/2015', 'mm/dd/yyyy') join_dt from dual union all
                     select 6141972 emp_id, 'Project manager' title, to_date('06/24/2015', 'mm/dd/yyyy') join_dt from dual union all
                     select 6163194 emp_id, 'QA engineer' title, to_date('06/01/2015', 'mm/dd/yyyy') join_dt from dual union all
                     select 6142464 emp_id, 'technician' title, to_date('05/18/2015', 'mm/dd/yyyy') join_dt from dual union all
                     select 6046935 emp_id, 'teacher' title, to_date('04/23/2015', 'mm/dd/yyyy') join_dt from dual)
-- end of setting up a subquery that mimicks a table with data in it. See sql below:
SELECT   emp_id,
         case when lead(emp_id) OVER (ORDER BY join_dt DESC, emp_id desc) is null
                   then first_value(emp_id) over (order by join_dt desc, emp_id desc
                                                  rows between unbounded preceding and current row)
              else lead(emp_id) OVER (ORDER BY join_dt DESC, emp_id desc)
         end next_emp_id,
         case when lead(emp_id) OVER (ORDER BY join_dt DESC, emp_id desc) is null
                   then first_value(title) over (order by join_dt desc, emp_id desc
                                                  rows between unbounded preceding and current row)
              else lead(title) OVER (ORDER BY join_dt DESC, emp_id desc)
         end next_title,
         case when lead(emp_id) OVER (ORDER BY join_dt DESC, emp_id desc) is null
                   then first_value(join_dt) over (order by join_dt desc, emp_id desc
                                                  rows between unbounded preceding and current row)
              else lead(join_dt) OVER (ORDER BY join_dt DESC, emp_id desc)
         end next_join_dt
from     sample_data
order by join_dt desc,
         emp_id desc;

    EMP_ID NEXT_EMP_ID NEXT_TITLE        NEXT_JOIN_DT
---------- ----------- ----------------- ------------
   6235396     6239577 radio engineer    08/05/2015  
   6239577     6219531 radar engineer    07/16/2015  
   6219531     6083501 software engineer 07/08/2015  
   6083501     6141972 Project manager   06/24/2015  
   6141972     6163194 QA engineer       06/01/2015  
   6163194     6142464 technician        05/18/2015  
   6142464     6046935 teacher           04/23/2015  
   6046935     6235396 doctor            09/05/2015  

以上查询假定 emp_id 不能为空。

【讨论】:

效果很好。谢谢你。但是,我还有另一列,更新了问题。当我运行查询时,我得到 ORA-01467: sort key too long 错误。知道为什么。没有该列,它执行得很好。 什么额外的列?我在问题中看不到它。无论如何,this from AskTom 应该有助于阐明错误。

以上是关于Oracle 潜在客户查询的主要内容,如果未能解决你的问题,请参考以下文章

在子表上选择查询

修补DBA短板:监控SQL优化案例两则

访问当月的 2010 查询

Laravel Eloquent 使查询执行变慢

oracle 查询

oracle 查询所有字段,某字段重复只显示一条