Oracle SQL - 在select中选择(在同一个表中!)

时间:2010-08-24 16:14:12

标签: sql oracle select join

我会尝试解释我想要快速实现的目标,因为我不知道如何解释它!

我们这里有一张表格,显示所有员工的所有工作经历,我想要当前帖子的“Start_Date”(“Current_Flag”='Y')。除此之外,我想要之前的帖子的“End_Date”(将按当前标记过滤,按结束日期排序,然后抓住顶部日期)

无论如何,这是我的代码:

SELECT "Gc_Staff_Number",
       "Start_Date",
       (SELECT "End_Date"
        FROM   "Employment_History"
        WHERE  "Current_Flag" != 'Y'
               AND ROWNUM = 1
               AND "Employee_Number" = "Employment_History"."Employee_Number"
        ORDER  BY "End_Date" ASC)
FROM   "Employment_History"
WHERE  "Current_Flag" = 'Y'

关于如何使这项工作的任何建议都很棒,希望上面的内容有点意义 - 说实话,此刻的查询甚至无法正常工作,嗯。

(编辑:哦!我写这个是为了查询一个现有的系统......由于某种原因,桌子周围有所有愚蠢的双引号和字段名称,叹了口气!)

6 个答案:

答案 0 :(得分:9)

这正是分析拯救的一种场景。

鉴于此测试数据:

SQL> select * from employment_history
  2  order by Gc_Staff_Number
  3             , start_date
  4  /

GC_STAFF_NUMBER START_DAT END_DATE  C
--------------- --------- --------- -
           1111 16-OCT-09           Y
           2222 08-MAR-08 26-MAY-09 N
           2222 12-DEC-09           Y
           3333 18-MAR-07 08-MAR-08 N
           3333 01-JUL-09 21-MAR-09 N
           3333 30-JUL-10           Y

6 rows selected.

SQL> 

带有分析LAG()函数的内联视图提供了正确的答案:

SQL> select Gc_Staff_Number
  2             , start_date
  3             , prev_end_date
  4  from   (
  5      select Gc_Staff_Number
  6             , start_date
  7             , lag (end_date) over (partition by Gc_Staff_Number
  8                                    order by start_date )
  9                  as prev_end_date
 10             , current_flag
 11      from employment_history
 12  )
 13  where current_flag = 'Y'
 14  /

GC_STAFF_NUMBER START_DAT PREV_END_
--------------- --------- ---------
           1111 16-OCT-09
           2222 12-DEC-09 26-MAY-09
           3333 30-JUL-10 21-MAR-09

SQL>

内联视图对于获得正确的结果至关重要。否则,CURRENT_FLAG上的过滤器将删除先前的行。

答案 1 :(得分:2)

我对引号感到有点困惑,但是,下面应该对你有用:

SELECT "Gc_Staff_Number",
       "Start_Date", x.end_date
FROM   "Employment_History" eh,
(SELECT "End_Date"
        FROM   "Employment_History"
        WHERE  "Current_Flag" != 'Y'
               AND ROWNUM = 1
               AND "Employee_Number" = eh.Employee_Number
        ORDER  BY "End_Date" ASC) x
WHERE  "Current_Flag" = 'Y'

答案 2 :(得分:2)

SELECT "Gc_Staff_Number",
       "Start_Date",
       (SELECT "End_Date"
        FROM   "Employment_History"
        WHERE  "Current_Flag" != 'Y'
               AND ROWNUM = 1
               AND "Employee_Number" = "Employment_History"."Employee_Number"
        ORDER  BY "End_Date" ASC)
FROM   "Employment_History"
WHERE  "Current_Flag" = 'Y'

仅供参考,在这种情况下,ROWNUM = 1在ORDER BY之前得到评估,因此内部查询将对(最多)一条记录的总计进行排序。

如果你真的在寻找给定员工最早的end_date(current_flag<>'Y'),那么你正在寻找什么?

SELECT "Gc_Staff_Number",
       "Start_Date",
       eh.end_date
  FROM "Employment_History" eh
       LEFT OUTER JOIN -- in case the current record is the only record...
       (SELECT "Employee_Number"
             , MIN("End_Date") as end_date
          FROM "Employment_History"
         WHERE "Current_Flag" != 'Y'
         GROUP BY "Employee_Number" 
       ) emp_end_date
          ON eh."Employee_Number" = emp_end_date."Employee_Number"
 WHERE eh."Current_Flag" = 'Y'

答案 3 :(得分:1)

SELECT eh."Gc_Staff_Number",
       eh."Start_Date",
       MAX(eh2."End_Date") AS "End_Date"
FROM   "Employment_History" eh
LEFT JOIN  "Employment_History" eh2
ON eh."Employee_Number" = eh2."Employee_Number" and eh2."Current_Flag" != 'Y'
WHERE  eh."Current_Flag" = 'Y' 
GROUP BY eh."Gc_Staff_Number",
       eh."Start_Date

答案 4 :(得分:1)

我将LAG function用于:

SELECT eh.gc_staff_number,
       eh.start_date,
       LAG(eh.end_date) OVER (PARTITION BY eh.gc_staff_number
                                  ORDER BY eh.end_date) AS prev_end_date
  FROM EMPLOYMENT_HISTORY eh
 WHERE eh.current_flag = 'Y'

如果你想提前一行,你可以使用LEAD function

兼容性:

据我所知,这支持9i +,但我还没有确认支持8i就像文档索赔一样。

LEAD和LAG最终是ANSI,但目前只有Oracle和PostgreSQL v8.4+支持它们。

答案 5 :(得分:0)

基本上,你所要做的就是

select ..., (select ... from ... where ...) as ..., ..., from ... where ...

例如。 您可以在任何地方插入(选择......从...到哪里),它将被相应的数据替换。

我知道其他人的例子(即使他们每个人真的很棒:))对新手来说有点复杂(比如我:p)所以我希望这个“简单”的例子可以帮助你们中的一些人:)