SQL包括没有数据的条目

时间:2015-02-19 02:24:34

标签: sql oracle join

这是我正在使用的Oracle中的sql语句:

SELECT FACILITY.fac_name
, SUM(FEE_LOG.fee_amount) AS TOTAL_FEES 
FROM FACILITY
, BOOK_DETAIL
, TRANS_LOG
, FEE_LOG
, TRANS_TYPE 
WHERE
FACILITY.fac_id = BOOK_DETAIL.fac_id 
AND BOOK_DETAIL.bkdt_id = TRANS_LOG.bkdt_id 
AND TRANS_LOG.trans_id = FEE_LOG.trans_id 
AND TRANS_LOG.trans_type_id = TRANS_TYPE.trans_type_id 
AND 
(
    TRANS_TYPE.trans_type_desc = 'LOST' 
    OR TRANS_TYPE.trans_type_desc = 'CHECKIN'
)
GROUP BY FACILITY.fac_name;

它会输出与此类似的内容:

FACILITY          TOTAL_FEES
Facility 1        8.45
Facility 2        4.23
Facility 3        5.23

我有2个其他设施,但他们没有任何相关的费用。我想把它们显示为0

所以输出就像:

FACILITY          TOTAL_FEES
Facility 1        8.45
Facility 2        4.23
Facility 3        5.23
Facility 4        0
Facility 5        0

ER图

ER Diagram

3 个答案:

答案 0 :(得分:2)

LEFT JOIN

使用INNER JOIN代替隐式FEE_LOG
SELECT FACILITY.fac_name
     , SUM(FEE_LOG.fee_amount) AS TOTAL_FEES 
FROM FACILITY
JOIN BOOK_DETAIL ON FACILITY.fac_id = BOOK_DETAIL.fac_id 
JOIN TRANS_LOG ON BOOK_DETAIL.bkdt_id = TRANS_LOG.bkdt_id 
LEFT JOIN FEE_LOG ON TRANS_LOG.trans_id = FEE_LOG.trans_id 
JOIN TRANS_TYPE  TRANS_LOG.trans_type_id = TRANS_TYPE.trans_type_id 
WHERE TRANS_TYPE.trans_type_desc IN ('LOST', 'CHECKIN')
GROUP BY FACILITY.fac_name;

答案 1 :(得分:0)

使用外连接和on子句:

SELECT FACILITY.fac_name, SUM(nvl(FEE_LOG.fee_amount,0)) AS TOTAL_FEES
  FROM FACILITY
  left join BOOK_DETAIL
    on FACILITY.fac_id = BOOK_DETAIL.fac_id
  left join TRANS_LOG
    on BOOK_DETAIL.bkdt_id = TRANS_LOG.bkdt_id
  left join FEE_LOG
    on TRANS_LOG.trans_id = FEE_LOG.trans_id
  left join TRANS_TYPE
    on TRANS_LOG.trans_type_id = TRANS_TYPE.trans_type_id
   and TRANS_TYPE.trans_type_desc in ('LOST', 'CHECKIN')
 GROUP BY FACILITY.fac_name;

注意:如果您所指的这些设施没有任何费用,则在BOOK_DETAIL或TRANS_LOG上有行,您可以使用内部联接替换外部联接(仅适用于那些表)。任何表格都可能存在或不存在相关记录,您必须使用外部联接。

答案 2 :(得分:0)

试试这个:

SELECT f.fac_name
, coalesce(SUM(fl.fee_amount),0) AS TOTAL_FEES 
FROM FACILITY AS f
INNER JOIN BOOK_DETAIL AS bd 
    ON bd.fac_id = f.fac_id
INNER JOIN TRANS_LOG AS tl
    ON tl.bkdt_id = bd.bkdt_id
LEFT OUTER JOIN FEE_LOG AS fl
    ON fl.trans_id = tl.trans_id
INNER JOIN TRANS_TYPE AS tt
    ON tt.trans_type_id = tl.trans_type_id 
WHERE tt.trans_type_desc in ('LOST' , 'CHECKIN')
GROUP BY f.fac_name;

注意:当您在from之后使用逗号列出表格时,您实际上正在使用cross join

当您将where语句中的条件添加到一个表中的字段与另一个表中的字段匹配时,该联接将变为inner join

要从一个表中选择所有记录以及可能存在或不存在其他匹配项,您需要outer join

有3种类型:

  • left outer join您希望列出第一个表中的所有记录以及第二个表中的所有匹配记录。
  • right outer join来自第二个的所有记录,只有第一个记录。
  • full outer join是两张桌子上的所有记录,并且是匹配的。

您应始终指定联接的类型,而不是通过where子句/逗号暗示它,因为这会使您的意图更清晰,从而使您的代码更具可读性。