如何组合(合并)类似的列以通过JOIN

时间:2015-12-03 16:24:22

标签: sql postgresql join null

问题简报:

我有一个名为“Customers”的超类表和两个继承自Customers的子表,名为“Person”和“Company”。因此,客户实体与“人”或“公司”具有一对一的关系。

(客户只能是“人”或“公司”,但两者都不能)

这表示如下:

Customer                    Person                      Company                
+-------+------+------+     +-------+------+------+     +-------+------+------+
|    cID|  col2|  col3|     |    cID| fname| sname|     |    cID|  name|  col3|
+-------+------+------+     +-------+------+------+     +-------+------+------+
|1      |?     |?     |     |1      |JJ    |AZ    |     |4      |ABCD  |?     |
+-------+------+------+     +-------+------+------+     +-------+------+------+
|2      |?     |?     |     |2      |CC    |LL    |     |5      |BCDE  |?     |
+-------+------+------+     +-------+------+------+     +-------+------+------+
|3      |?     |?     |     |3      |OO    |BB    |     |6      |CDEF  |?     |
+-------+------+------+     +-------+------+------+     +-------+------+------+
|4      |?     |?     |     |7      |JK    |NN    |     |8      |DEFG  |?     |
+-------+------+------+     +-------+------+------+     +-------+------+------+
|5      |?     |?     |     |9      |RR    |LW    |     |...    |EFGH  |?     |
+-------+------+------+     +-------+------+------+     +-------+------+------+
|6      |?     |?     |     |10     |GN    |QN    |     |...    |FGHI  |?     |
+-------+------+------+     +-------+------+------+     +-------+------+------+
|7      |?     |?     |     |...    |XC    |YU    |     |...    |GHIJ  |?     |
+-------+------+------+     +-------+------+------+     +-------+------+------+
|8      |?     |?     |
+-------+------+------+
|9      |?     |?     |
+-------+------+------+
|10     |?     |?     |
+-------+------+------+
|...    |?     |?     |
+-------+------+------+
  • Person表以单独的firstname和surname属性存储Customer的全名。
  • 公司表完全将公司名称存储在一个字段中。

意图&尝试:

我想要查询数据库,以便我可以从Customer表中选择ID,加入Person和Company以检索name属性。

以下是我的尝试:

SELECT      tc."cust_id",
            CONCAT(tp."forename", ' ', tp."surname") AS "name",
            tcp."name"
FROM        "tbl_customer" AS tc
            LEFT JOIN "tbl_person" AS tp
                ON tc."cust_id" = tp."cust_id"
            LEFT JOIN "tbl_company" AS tcp
                ON tc."cust_id" = tcp."cust_id"

执行上面的SQL给出了以下结果,而右边是我想要实现的目标:

Result                      Result          
+-------+------+------+     +-------+------+
|    cID|  name|  name|     |    cID|  name|
+-------+------+------+     +-------+------+
|1      |JJAZ  |null  |     |1      |JJAZ  |
+-------+------+------+     +-------+------+
|2      |CCLL  |null  |     |2      |CCLL  |
+-------+------+------+     +-------+------+
|3      |OOBB  |null  |     |3      |OOBB  |
+-------+------+------+     +-------+------+
|4      |null  |ABCD  |     |4      |ABCD  |
+-------+------+------+     +-------+------+
|5      |null  |BCDE  |     |5      |BCDE  |
+-------+------+------+     +-------+------+
|6      |null  |CDEF  |     |6      |CDEF  |
+-------+------+------+     +-------+------+
|7      |JKNN  |null  |     |7      |JKNN  |
+-------+------+------+     +-------+------+
|8      |null  |DEFG  |     |8      |DEFG  |
+-------+------+------+     +-------+------+
|9      |RRLW  |null  |     |9      |RRLW  |
+-------+------+------+     +-------+------+
|10     |GNQN  |null  |     |10     |GNQN  |
+-------+------+------+     +-------+------+
|...    |?     |?     |     |...    |?     |
+-------+------+------+     +-------+------+

说明

如上所述,我试图在同一列中合并Person和Company的名称。两个表上的标准JOIN都不起作用,因为它将返回NULL结果。由于LEFT JOIN的性质,可以预期NULL值。这可以通过SQL UNION非常简单地解决,我知道解决方案,但是我正在通过JOIN寻找UNION运算符的替代方案。

无论如何我可以执行JOIN,分组/合并名称列吗?或类似的东西?但是不必使用SQL UNION?

更新

Juan Carlos Oropeza Becuzz 的答案同样可以接受。

2 个答案:

答案 0 :(得分:3)

COALESCE听起来会完全按照你的意愿行事。 COALESCE是一个函数,它返回其参数的第一个非NULL值。

SELECT      tc."cid",
            COALESCE(tp.firstName||' '||tp.lastName, tcp.name) as "name"
FROM        "customers" AS tc
            LEFT JOIN "person" AS tp
                ON tc."cid" = tp."cid"
            LEFT JOIN "company" AS tcp
                ON tc."cid" = tcp."cid"

SQL Fiddle

答案 1 :(得分:2)

只需添加CASE即可选择使用哪种数据

SELECT      tc."cust_id",
            CASE WHEN tp."forename" IS NULL 
                   THEN tcp."name"
                 ELSE  CONCAT(tp."forename", ' ', tp."surname") 
            AS "name"
FROM        "tbl_customer" AS tc
            LEFT JOIN "tbl_person" AS tp
                ON tc."cust_id" = tp."cust_id"
            LEFT JOIN "tbl_company" AS tcp
                ON tc."cust_id" = tcp."cust_id"