条件加入SQL Server

时间:2015-07-01 21:22:55

标签: sql sql-server join

我有一个场景如下:

Source1的

Column1 
Column2

源2

Column1
Column2

输出 - 我需要一个视图;

Source2中Column2不为空的所有记录都必须在视图中。

Source2中Column2为空的所有记录必须与Source2连接(在Column1上,两个表之间的引用)。无论在何处找到匹配项,Source2的Column2也应包含在视图中。

请指点..

3 个答案:

答案 0 :(得分:1)

我看到的最简单方法是使用两个查询的并集:

SELECT * FROM Source1 WHERE Column2 IS NOT NULL
UNION
SELECT S2.* FROM Source1 S1
INNER JOIN Source2 S2
ON S1.Column1 = S2.Column1
WHERE S1.Column2 IS NULL

答案 1 :(得分:1)

那么回顾一下:只包括填充了Source1.Column2的行,如果还填充了Source2,还包括Source2的Column2?

您正在寻找的是LEFT JOIN。学习并喜欢它,因为它是整个SQL中最便捷的东西之一。

   SELECT s1.Column1, s1.Column2, s2.Column2
     FROM source1 s1
LEFT JOIN source2 s2 ON s1.Column1 = s2.Column1
    WHERE s1.Column2 IS NOT NULL

答案 2 :(得分:1)

Source1Source2之间使用外部联接

规格有点宽松。您是否希望Column2中的Source2作为单独的(第三列)列返回,或者您是否希望第二列中的值更换为Column2的“空”值来自Source1

Column2Source1Source2的数据类型是什么?是字符类型,数字,日期时间?

你如何定义“空”?对于字符类型,是否包括NULL值和零长度字符串?

此外,表之间关系的基数是一对一,一对多(哪种方式)。它是强制性的,还是可能是零?

假设您想要所有行(如果Source2中有多行与Source1中的行匹配,并假设您需要第三列,并假设Column2的数据类型是字符,假设“空”表示NULL或零长度字符串(这是很多假设)......然后是这样的:

  SELECT s.column1
       , s.column2
       , IF(IFNULL(s.column2,'')='',t.column2,'') AS t_column2
    FROM source1 s
    LEFT
    JOIN source2 t
      ON t.column1 = s.column1
     AND IFNULL(s.column2,'') = ''
   ORDER BY s.column1, 2, 3

...将返回符合规范的结果。可以更改/调整该查询以适应更严格(更精确)的规范。

修改

糟糕!

上面的示例查询基于另一个假设:这是MySQL特有的。

上述语句的语法在其他数据库中不会“起作用”。这是一个等效语句,使用更多符合ANSI标准的语法:

  SELECT s.column1
       , s.column2
       , CASE WHEN s.column2 IS NULL OR s.column2 = ''
           THEN t.column2
           ELSE ''
         END AS t_column2
    FROM source1 s
    LEFT
    JOIN source2 t
      ON t.column1 = s.column1
     AND (s.column2 IS NULL OR s.column2 = '')
   ORDER BY s.column1, s.column2

<强>后续

添加了一个演示行为的示例:

SQL Fiddle here: http://sqlfiddle.com/#!9/113e6/1

设置表格和示例行:

  CREATE TABLE source1
  ( id      INT UNSIGNED AUTO_INCREMENT PRIMARY KEY
  , column1 INT
  , column2 VARCHAR(8)
  );
  CREATE TABLE source2
  ( id      INT UNSIGNED AUTO_INCREMENT PRIMARY KEY
  , column1 INT
  , column2 VARCHAR(8)
  );
  INSERT INTO source1 (id, column1, column2) VALUES
   (1,NULL,NULL)
  ,(2,NULL,'foo')
  ,(3,113,'fee')
  ,(4,114,'fi')
  ,(5,115,'')
  ,(6,116,NULL)
  ,(7,122,'fo')
  ,(8,122,'fum')
  ;
  INSERT INTO source2 (id, column1, column2) VALUES
   (21,NULL,'doh')
  ,(22,113,'rey')
  ,(23,113,'mii')
  ,(24,114,'fah')
  ,(25,115,'sew')
  ,(26,115,'lah')
  ,(27,116,NULL)
  ,(28,116,'')
  ,(29,116,'tea')
  ,(30,116,'doh')
  ;

示例查询(与上面的查询相同):

  SELECT s.column1
       , s.column2
       , IF(IFNULL(s.column2,'')='',t.column2,'') AS t_column2
    FROM source1 s
    LEFT
    JOIN source2 t
      ON t.column1 = s.column1
     AND IFNULL(s.column2,'') = ''
   ORDER BY s.column1, 2, 3

示例查询 - 与上面的PLUS额外ID列

相同
  SELECT s.column1
       , s.column2
       , IF(IFNULL(s.column2,'')='',t.column2,'') AS t_column2
      -- ---------------
       , s.id AS s_id
       , t.id AS t_id
      -- ---------------
    FROM source1 s
    LEFT
    JOIN source2 t
      ON t.column1 = s.column1
     AND IFNULL(s.column2,'') = ''
   ORDER BY s.column1, 2, 3

返回:

    column1  column2  t_column2    s_id    t_id
    -------  -------  ---------  ------  --------
     (NULL)  (NULL)   (NULL)          1    (NULL)
     (NULL)  foo                      2    (NULL)
        113  fee                      3    (NULL)
        114  fi                       4    (NULL)
        115           lah             5        26
        115           sew             5        25
        116  (NULL)   (NULL)          6        27
        116  (NULL)                   6        28
        116  (NULL)   doh             6        30
        116  (NULL)   tea             6        29
        122  fo                       7    (NULL)
        122  fum                      8    (NULL)

请注意,此示例在{1}}和source1的第1列中包含“重复”值,并显示返回的结果。 (包含source2s_id列有助于解密返回的行。)