SQL Server中的外部联接问题

时间:2009-08-28 13:55:15

标签: sql sql-server

这是我的查询。我想要BF的所有行和FT的匹配行。它只返回2行,但实际行数为135.我该如何更改查询?

SELECT 
  BF.FaturaNo,
  K.KlinikAdi,
  FT.teslimAlindi,
  FT.TeslimAciklama,
  FT.kurumTeslimAldi,
  FT.kurumTeslimAciklama,
  BF.basilmisFatura_id,
  K.klinik_id
FROM 
  BasilmisFaturalar AS BF
LEFT OUTER JOIN 
  FaturaTeslim AS FT 
  ON FT.refBasilmisFatura_id = BF.BasilmisFatura_id
INNER JOIN 
  Klinikler AS K 
  ON BF.refKlinik_id = K.klinik_id
INNER JOIN 
  Faturalar AS F 
  ON F.refBasilmisFatura_id = BF.basilmisFatura_id
WHERE 
      BF.FaturaNo LIKE '%%'
  AND BF.refklinik_id IN ('24','25','26','27')
  AND MONTH(F.faturaTarihi) = 7 
  AND teslimAlindi = 0 
  AND kurumTeslimAldi = 0
GROUP BY 
  F.refBasilmisFatura_id,
  BF.FaturaNo,
  K.KlinikAdi,
  FT.teslimAlindi,
  FT.TeslimAciklama,
  FT.kurumTeslimAldi,
  FT.kurumTeslimAciklama,
  BF.basilmisFatura_id,
  K.klinik_id
ORDER BY
  faturaNo ASC

4 个答案:

答案 0 :(得分:2)

您的teslimAlindi和kurumTeslimAldi过滤器位于“OUTER”侧,因此请将此BF加入为INNER JOIN。

在加入或过滤ON子句之前,需要先过滤。我更喜欢这个派生表方法

    ....
FROM BasilmisFaturalar AS BF
    LEFT OUTER JOIN
    (SELECT *
    FROM
        FaturaTeslim
    WHERE
        teslimAlindi = 0 AND 
        kurumTeslimAldi = 0
    )  AS FT ON FT.refBasilmisFatura_id = BF.BasilmisFatura_id
    INNER JOIN Klinikler AS K ON BF.refKlinik_id = K.klinik_id
    INNER JOIN Faturalar AS F ON F.refBasilmisFatura_id = BF.basilmisFatura_id
WHERE BF.FaturaNo LIKE '%%' AND 
    BF.refklinik_id IN ('24','25','26','27') AND 
    MONTH(F.faturaTarihi) = 7 

答案 1 :(得分:2)

你的where子句中有teslimAllindi和kurumTeslimAldi。

连接在where子句之前执行。因此,对于没有FakturaTeslim记录的每一行,加入后TeslimAllindi和KurumTeslimAldi将为NULL。

这些行将被where子句过滤掉,从而有效地使左连接作为内连接工作。

你应该写这个:

SELECT 
  BF.FaturaNo,
  K.KlinikAdi,
  FT.teslimAlindi,
  FT.TeslimAciklama,
  FT.kurumTeslimAldi,
  FT.kurumTeslimAciklama,
  BF.basilmisFatura_id,
  K.klinik_id
FROM 
  BasilmisFaturalar AS BF
LEFT OUTER JOIN 
  FaturaTeslim AS FT 
  ON 
    (FT.refBasilmisFatura_id = BF.BasilmisFatura_id
     AND teslimAlindi = 0 
     AND kurumTeslimAldi = 0)
INNER JOIN 
  Klinikler AS K 
  ON BF.refKlinik_id = K.klinik_id
INNER JOIN 
  Faturalar AS F 
  ON F.refBasilmisFatura_id = BF.basilmisFatura_id
WHERE 
      BF.FaturaNo LIKE '%%'
  AND BF.refklinik_id IN ('24','25','26','27')
  AND MONTH(F.faturaTarihi) = 7 
GROUP BY 
  F.refBasilmisFatura_id,
  BF.FaturaNo,
  K.KlinikAdi,
  FT.teslimAlindi,
  FT.TeslimAciklama,
  FT.kurumTeslimAldi,
  FT.kurumTeslimAciklama,
  BF.basilmisFatura_id,
  K.klinik_id
ORDER BY
  faturaNo ASC

答案 2 :(得分:2)

WHERE子句有

 AND teslimAlindi = 0  
 AND kurumTeslimAldi = 0  

假设那些不受约束的列来自表FaturaTeslim,你所说的是有效的:
  - 从BasilmisFaturalar中获取所有需要的行   - 将它们与FaturaTeslim中的任何行匹配,但如果没有找到则可以   - 并且在这些结果中,抛出teslimAlindi<>的所有行。 0 kurumTeslimAldi<> 0

对于左外连接,对于那些在FaturaTeslim中找不到匹配的行,teslimAlindi和kurumTeslimAldi将为NULL,并通过where子句将它们删除(因为它们不是= 0)。

gbn的代码片段通过检查外部联接的ON子句中的那些值来说明如何解决这个问题 - 这是您希望实现的业务逻辑的IF(也就是说,只有LOJ那些FaturaTeslim行,其中teslimAlindi = 0和kurumTeslimAldi = 0

答案 3 :(得分:-1)

您的WHERE条款可能比您认为的更具限制性。尝试取出其中的一些条款。

此外,BF.FaturaNo LIKE '%%'可能应该用更易于理解的BF.FaturaNo IS NOT NULL

替换

尝试将问题简化为更简单的概念演示。你在这个问题中有太多特定于数据模型的东西。