SQL LEFT JOIN和GROUP BY

时间:2016-01-07 13:16:11

标签: sql sql-server sql-server-2008 join group-by

我有一个表T_DONNE,它只是数据导入的类型。 Noid =身份证 Libelle =标签

NOID    LIBELLE
1       WEB
2       FTP

客户:

CODE_CL   RS_NOM  VILLE      TYPE_CLIENT
85000     test    La roche   1
85001     azerty  Nantes     2
85002     qsdfg   Nantes     1

LETTRE_VOIT_FINAL:就像客户指定的项目一样

  NOID  CODE_CLIENT RS_NOM   VILLE_EXP  FACTURATION   DATE_CLOTUR_REEL
  1     85000       test     La roche   2             2016-01-07 15:02:59
  2     85000       test     La roche   2             2016-01-07 15:03:59
  3     85001       azerty   Nantes     2             2016-01-07 15:04:59

我想要的是:

CODE_CLIENT  RS_NOM    VILLE_EXP  LIBELLE  TOTAL
85000        test      La roche   WEB      2
85001        azerty    Nantes     FTP      1
85002        qsdfg     Nantes     WEB      0

和sql:

SELECT           
       LETTRE_VOIT_FINAL.CODE_CLIENT
      ,LETTRE_VOIT_FINAL.RS_NOM
      ,LETTRE_VOIT_FINAL.VILLE_EXP         
      ,T_DONNE.LIBELLE
      ,count (LETTRE_VOIT_FINAL.NOID) as TOTAL    
FROM LETTRE_VOIT_FINAL 
LEFT OUTER JOIN CLIENT ON CLIENT.CODE_CL  = LETTRE_VOIT_FINAL.CODE_CLIENT  
LEFT JOIN T_DONNE ON T_DONNE.NOID = CLIENT.TYPE_CLIENT

WHERE DATE_CLOTUR_REEL BETWEEN @DateDeb AND @DateFin
and FACTURATION = @FACTURATION
and STATUT_LV = 2  
group by CODE_CLIENT,VILLE_EXP,RS_NOM,LIBELLE

它不太有用。它只显示:

  CODE_CLIENT  RS_NOM    VILLE_EXP   LIBELLE  TOTAL
    85000        test      La roche   WEB      2
    85001        azerty    Nantes     FTP      1

我认为它因NULL值和计数功能而无效。

我想列出所有客户并计算他/她指令的项目。 我的语法只显示有命令的客户端,我错过了我的例子中未命令的客户端是客户端85002

我也倒了但仍然得到了相同的结果:

SELECT 
    count (LETTRE_VOIT_FINAL.NOID) as TOTLV
    ,CODE_CL
    ,VILLE
    ,[RS_NOM]
    ,LIBELLE
FROM CLIENT 
LEFT JOIN LETTRE_VOIT_FINAL ON CLIENT.CODE_CL  = LETTRE_VOIT_FINAL.CODE_CLIENT  
LEFT JOIN T_DONNE ON T_DONNE.NOID = CLIENT.TYPE_CLIENT   

WHERE DATE_CLOTUR_REEL BETWEEN @DateDeb AND @DateFin
and FACTURATION = @FACTURATION
and STATUT_LV = 2  

group by CODE_CL,VILLE,RS_NOM,LIBELLE

@DateDeb datetime,@ DateFin datetime,@ FACTURATION int',@ DateDeb =' 2016-01-07 12:00:00',@ DateFin =' 2016-01- 07 23:59:59',@ FACTURATION = 2

5 个答案:

答案 0 :(得分:1)

根据您的预期结果,您的值似乎来自Client表,但您的查询(和列名称)显示您正在尝试从Lettre_Voit_Final表中获取它们。我认为这是你最大的问题。通过从Client表开始,您可以加入到LEFT OUTER JOIN,以确保您仍然可以获取Client表中的所有行,即使该行的另一个表中不存在任何行。

SELECT
    C.code_client,
    C.rs_nom,
    C.ville,
    D.libelle,
    COUNT(*)
FROM
    Client C
INNER JOIN T_Donne D ON D.noid = C.type_client
LEFT OUTER JOIN Lettre_Voit_Final LVF ON LVF.code_client = C.code_cl
GROUP BY
    C.code_client,
    C.rs_nom,
    C.ville,
    D.libelle

其他一些说明......

您的列名似乎不一致(例如,code_client与code_cl)。这确实会减慢开发速度并导致其他编码错误。

使用ville与ville_exp可能会有一些重复的数据(虽然我不确定)。也许其中一个是"默认"值和另一个实际值或其他东西,并在您的数据库中有意义,但只是要注意的其他事项。

答案 1 :(得分:0)

您的查询流程LETTRE_VOIT_FINAL => CLIENT => T_DONNE

但您在表CLIENT中使用左连接记录(行)无法连接(即 - 不具有由join子句声明的对应键)将不会被带到结果集。将其更改为完全加入/右连接或更改表连接的顺序

SELECT 
      count (LETTRE_VOIT_FINAL.NOID as TOTLV

      ,[CODE_CLIENT]
      ,VILLE_EXP
      ,[RS_NOM]
      ,LIBELLE
  FROM [LETTRE_VOIT_FINAL] 
  FULL OUTER JOIN CLIENT ON CLIENT.CODE_CL  = LETTRE_VOIT_FINAL.CODE_CLIENT  
  FULL OUTER T_DONNE ON T_DONNE.NOID = CLIENT.TYPE_CLIENT
  where 
 DATE_CLOTUR_REEL BETWEEN @DateDeb AND @DateFin
  and FACTURATION = @FACTURATION
   and STATUT_LV = 2  
   group by CODE_CLIENT,VILLE_EXP,RS_NOM,LIBELLE

答案 2 :(得分:0)

您正在引用LETTRE_VOIT_FINAL,我认为您不想这样做。既然您已经添加了更多信息,我已经用子查询重写了查询。您也可以使用join子句来完成它。无论如何,您无法在整个查询中执行此操作。此查询生成您要创建的表

  Select client.code_cl
  , client.rs_nom
  , client.ville
  , t_donne.libelle
  , COUNT(l.noid) As total
  From client
  Inner join t_donne on t_donne.noid = client.type_client
  Left outer join (
      Select noid, code_client
      From lettre_voit_final 
      Where facturation = @facturation 
      and date_clotur_reel between @DateDeb and @DateEnd
      and status_lv = 2
  ) as l on l.code_client = client.code_cl
  group by client.code_cl
  , client.rs_nom
  , client.ville
  , t_donne.libelle

首先,客户端表与标签值连接,这将为您提供:

85000   test    La roche    WEB
85001   azerty  Nantes  FTP
85002   qsdfg   Nantes  WEB

然后left outer join用于包含所有这些值加上lettre_voit_final表的子选行中具有这些值的行数,以便为您提供:

85000   test    La roche    WEB 2
85001   azerty  Nantes  FTP 1
85002   qsdfg   Nantes  WEB 0

答案 3 :(得分:0)

我明白了,谢谢你的所有意见。

  SELECT           
       CLIENT.CODE_CL
      ,CLIENT.RS_NOM
      ,CLIENT.VILLE  
      ,T_DONNE.LIBELLE
      ,count (LETTRE_VOIT_FINAL.NOID) as TOTLV    
  FROM CLIENT
 LEFT OUTER JOIN 
  (

  SELECT *
        FROM   LETTRE_VOIT_FINAL 
        WHERE DATE_CLOTUR_REEL BETWEEN @DateDeb AND @DateFin
        and FACTURATION = @FACTURATION
        and STATUT_LV = 2 

        )
   LETTRE_VOIT_FINAL ON  CLIENT.CODE_CL  = LETTRE_VOIT_FINAL.CODE_CLIENT  
  LEFT JOIN T_DONNE ON T_DONNE.NOID = CLIENT.TYPE_CLIENT

where type_client != 0

   group by CLIENT.CODE_CL,CLIENT.VILLE,CLIENT.RS_NOM,LIBELLE

答案 4 :(得分:0)

你不需要那个派生表来回答

SELECT CLIENT.CODE_CL
      ,CLIENT.RS_NOM
      ,CLIENT.VILLE  
      ,T_DONNE.LIBELLE
      ,count (LETTRE_VOIT_FINAL.NOID) as TOTLV    
 FROM CLIENT
 LEFT JOIN LETTRE_VOIT_FINAL
        on LETTRE_VOIT_FINAL.CODE_CLIENT = CLIENT.CODE_CL 
       and LETTRE_VOIT_FINAL.DATE_CLOTUR_REEL BETWEEN @DateDeb AND @DateFin
       and LETTRE_VOIT_FINAL.FACTURATION = @FACTURATION
       and LETTRE_VOIT_FINAL.STATUT_LV = 2    
 LEFT JOIN T_DONNE 
        ON T_DONNE.NOID = CLIENT.TYPE_CLIENT
where CLIENT.TYPE_CLIENT != 0
group by CLIENT.CODE_CL, CLIENT.VILLE, CLIENT.RS_NOM,LIBELLE