我正在进行一个简单的查询,我将从两个表中显示数据。条件是如果alloment表有数据并且leave详细信息没有数据,那么它应该仅显示分配表中的数据。就我而言,当两个表都有数据时,它会显示数据。试过这个但是当两个表都有数据时返回:
SELECT K.EMPNO, K.LV_NAME, K.ALLOTMENT, K.REMAIN, M.LV_FROM, M.LV_TO
FROM LV_ADJ_DETAILS m
LEFT JOIN TBL_LV_ALLOTMENT k
ON M.EMPNO = K.EMPNO
WHERE K.EMPNO = 'EMP00259'
AND K.YEAR_NAME = '2018'
AND EXTRACT(YEAR FROM M.LV_TO) = '2018';
预期产出: 2018年
如果两个表都有数据 -
EMPNO LV_NAME ALLOTMENT REMAIN LV_FROM LV_TO
EMP00259 MLWP 0 0 4/22/2018 4/30/2018
EMP00259 Maternity Leave 103 103 5/20/2018 5/22/2018
EMP00259 MLWP 0 0 5/24/2018 5/26/2018
EMP00259 Maternity Leave 103 103 5/28/2018 5/30/2018
如果一个表有数据 - 如果没有留下详细信息,例如离开和到
EMPNO LV_NAME ALLOTMENT REMAIN LV_FROM LV_TO
EMP00259 MLWP 0 0
EMP00259 Maternity Leave 103 103 103
脚本:
CREATE TABLE HRD.TBL_LV_ALLOTMENT
(
EMPNO VARCHAR2(10 BYTE),
LV_NAME VARCHAR2(30 BYTE),
YEAR_NAME INTEGER,
ALLOTMENT NUMBER,
ENJOY NUMBER,
REMAIN NUMBER,
STATUS INTEGER
)
CREATE TABLE HRD.LV_ADJ_DETAILS
(
EMPNO VARCHAR2(20 BYTE),
APP_NO VARCHAR2(10 BYTE),
LEAVE_NAME VARCHAR2(30 BYTE),
APV_DAYS NUMBER(3),
LV_FROM DATE,
LV_TO DATE,
BALANCE NUMBER(3),
COM_ID VARCHAR2(15 BYTE)
)
注意:我在WHERE
子句中使用年份进行过滤。
答案 0 :(得分:3)
外连接的第一件事是使表顺序正确。使用LEFT OUTER JOIN,包含所有表的表在连接之前出现,并且表中包含一些表。你说......
如果alloment表有数据并且请假详细信息没有数据,那么它应该只显示分配表中的数据
...所以正确的连接顺序是tbl_lv_allotment k left outer join lv_adj_details m
。
在外连接中进行过滤时,还有一个陷阱,你已经成为它的牺牲品。通过在WHERE子句标准中包含m.lv_to
,您将丢弃m.lv_to
为空的任何行,这会使外连接短路。有几种方法可以解决这个问题,但最简单的方法是测试null:
select k.empno
, k.lv_name
, k.allotment
, k.remain
, m.lv_from
, m.lv_to
from tbl_lv_allotment k
left outer join lv_adj_details m
on m.empno = k.empno
where k.empno = 'EMP00259'
and k.year_name = '2018'
and ( m.lv_to is null or extract(year from m.lv_to) = '2018' );
但是,根据您的数据,使用子查询可能更好:
select k.empno
, k.lv_name
, k.allotment
, k.remain
, m.lv_from
, m.lv_to
from tbl_lv_allotment k
left outer join ( select * from lv_adj_details
where extract(year from lv_to) = '2018' ) m
on m.empno = k.empno
where k.empno = 'EMP00259'
and k.year_name = '2018'
;
以下是使用查询版本的a demo on SQL Fiddle,显示了WHERE子句如何颠覆外部联接。
在小提琴中,我改变了连接标准以包含and m.leave_name = k.lv_name
。这将删除从一个表中的所有行与另一个表中的所有行匹配所得到的可怕产品。我在这里没有这样做,因为我认为答案中的代码应该产生问题中显示的输出。
答案 1 :(得分:2)
您希望从表格Error while requesting the database « -- » : invalid command name "parray"
中选择,并从表格tbl_lv_allotment
中选择外部联接记录,但反之亦然。
然后想象主表在外连接表中没有匹配的情况。然后得到一行,外连接表的所有列都为null。如果您在该表的lv_adj_details
子句中有条件(例如查询中的WHERE
),则立即关闭该行,因为在外部连接行中此值为null。这使您的外部联接仅仅是内部联接。外连接表的标准属于K.EMPNO = 'EMP00259'
子句:
ON
我已将select a.empno, a.lv_name, a.allotment, a.remain, d.lv_from, d.lv_to
from tbl_lv_allotment a
left join lv_adj_details d on d.empno = a.empno
and to_char(d.lv_to, 'yyyy') = a.year_name
where a.empno = 'EMP00259'
and a.year_name = '2018';
(应该是EXTRACT(YEAR FROM M.LV_TO) = '2018'
,而不是2018
,因为您正在处理此处的数字)更改为'2018'
,因为很明显这是关于匹配的主表年。
答案 2 :(得分:1)
where子句中的这个条件(AND EXTRACT(YEAR FROM M.LV_TO) = '2018')
会产生问题。
试试这个:
SELECT K.EMPNO, K.LV_NAME, K.ALLOTMENT, K.REMAIN, M.LV_FROM, M.LV_TO
FROM LV_ADJ_DETAILS m
LEFT JOIN TBL_LV_ALLOTMENT k
ON M.EMPNO = K.EMPNO AND EXTRACT(YEAR FROM M.LV_TO) = '2018'
WHERE K.EMPNO = 'EMP00259' AND K.YEAR_NAME = '2018';