Sql 确定聚结场上的源

Sql 确定聚结场上的源,sql,postgresql,left-join,coalesce,Sql,Postgresql,Left Join,Coalesce,我有两个表,它们的结构相同,但属于不同的模式A和B。所有有问题的行将始终出现在A.表中,但可能出现在B.表中,也可能不出现在B.表中。B.table本质上是A.table中默认值的覆盖 因此,我的查询在每个字段上使用合并,类似于: SELECT COALESCE(B.id, A.id) as id, COALESCE(B.foo, A.foo) as foo, COALESCE(B.bar, A.bar) as bar FROM A.table LEFT JOIN B

我有两个表,它们的结构相同,但属于不同的模式A和B。所有有问题的行将始终出现在A.表中,但可能出现在B.表中,也可能不出现在B.表中。B.table本质上是A.table中默认值的覆盖

因此,我的查询在每个字段上使用合并,类似于:

SELECT COALESCE(B.id, A.id) as id,
       COALESCE(B.foo, A.foo) as foo,
       COALESCE(B.bar, A.bar) as bar
FROM A.table LEFT JOIN B.table ON (A.id = B.id)
WHERE A.id in (1, 2, 3)
这非常有效,但我还想添加数据源。在上面的例子中,假设id=2存在于B.table中,但不是1或3,我想包括一些指示,表明A是1和3的源,B是2的源

因此,数据可能如下所示

+---------------------------------+
|  id  |  foo  |  bar  |  source  |
+---------------------------------+
|   1  |    a  |    b  |       A  |
|   2  |    c  |    d  |       B  |
|   3  |    e  |    f  |       A  |
+---------------------------------+
只要我能区分A和B,我并不在乎source的值是多少


我不是pgsql专家,但我已经修补了EXISTS和子查询,但到目前为止运气不好。

由于显示a.table默认值的记录的B.id为空,您只需将此列规范添加到查询中:

CASE WHEN B.id IS NULL THEN 'A' ELSE 'B' END AS Source
USING子句将简化您的查询:

SELECT id
     , COALESCE(B.foo, A.foo) AS foo
     , COALESCE(B.bar, A.bar) AS bar
     , CASE WHEN b.id IS NULL THEN 'A' ELSE 'B' END AS source  -- like @Terje provided
FROM   a
LEFT   JOIN b USING (id)
WHERE  a.id IN (1, 2, 3);
优点:

您不必为要添加到结果中的每一列添加另一个合并构造。 相同的查询适用于a和b中任意数量的列。 即使列名不相同,查询也可以工作。只有列的数量和数据类型必须匹配。 当然,您也可以始终列出选定的兼容列:

SELECT *  --  or list columns of your choice
FROM  (VALUES (1), (2), (3)) t (id)
     , LATERAL (
   SELECT foo, bar, 'B' AS source FROM b WHERE id = t.id
   UNION ALL
   SELECT foo2, bar17, 'A'        FROM a WHERE id = t.id
   LIMIT 1
   ) x
ORDER  BY x.id;
第一个选择确定名称、数据类型和列数

如果b中的列未定义为NOTNULL,则此查询不会中断。 COALESCE无法区分b.foo为NULL和b中没有id匹配的行之间的区别。因此,除id之外的任何结果列的源仍然可以是“A”,即使结果行显示“B”-如果B中的任何相关列都可以为NULL。 如果行存在,我的备选方案将返回b中的所有值,包括空值。因此,如果b中的列可以为NULL,则结果可能不同。这取决于你的要求,哪种行为是可取的。 这两个查询都假定id被定义为主键,因此每个给定id值正好有1或0行

相关的:


美丽的这么简单,但我还是逃避了。谢谢。使用简单的合并表达式,如果B.foo可以为NULL(这一点没有被排除),那么foo的源仍然可以是A,即使B.id不为NULL。谢谢您的回答和详细的分析。由于表的列数不同,所以我猜第二个表不起作用。不管怎样读都很有趣。@sberry:第二本也适用。在横向查询中,不能使用SELECT*的语法快捷方式。我添加了一个示例和一些解释。
SELECT *  --  or list columns of your choice
FROM  (VALUES (1), (2), (3)) t (id)
     , LATERAL (
   SELECT foo, bar, 'B' AS source FROM b WHERE id = t.id
   UNION ALL
   SELECT foo2, bar17, 'A'        FROM a WHERE id = t.id
   LIMIT 1
   ) x
ORDER  BY x.id;