当列可用时进行 Sql 连接,否则与剩余列连接?

问题描述 投票:0回答:4

我想将表

T1
与列
T2
上的
a,b,c
左连接。

我首先尝试加入所有三列,但它们没有加入,所以现在作为后备,我加入列

a,b

我该如何实施?

示例

T1:

+---+---+---+-------+
| a | b | c | mycol |
+---+---+---+-------+
| 1 | 2 | 3 | john  |
| 1 | 3 | 4 | cena  |
+---+---+---+-------+

T2:

+---+---+---+-------+
| a | b | c | value |
+---+---+---+-------+
| 1 | 2 | 3 |    10 |
| 1 | 3 |   |    20 |
+---+---+---+-------+

加入后:

+---+---+---+-------+-------+
| a | b | c | mycol | value |
+---+---+---+-------+-------+
| 1 | 2 | 3 | john  |    10 |
| 1 | 3 | 4 | cena  |    20 |
+---+---+---+-------+-------+
sql subquery left-join
4个回答
2
投票

大概,您需要两个左连接和条件逻辑

select t1.*, coalesce(t20.a, t21.a) a2, coalesce(t20.b, t21.b) b2, coalesce(t20.c, t21.c) c2
from t1
left join t2 t20 
    on t20.a = t1.a  and t20.b = t1.b and t20.c = t1.c
left join t2 t21
    on t20.a is null and t21.b = t1.b and t21.c = t1.c

第一个左连接尝试在三列上进行匹配。第二个连接仅在前两列上连接,并且仅当第一个连接返回空时才连接。然后,您可以在

coalesce()
子句中使用
select
来带来相关值。


0
投票
select t1.*, coalesce(
         (select t20.value from t20 where t20.a = t1.a and t20.b = t1.b and t20.c = t1.c),
         (select t21.value from t21 where t21.a = t1.a and t21.b = t1.b )) as "value"
 from t1

对于第二个内部选择,您必须确保它获得唯一的结果。因此,您可能必须将结果限制为 1,但如何执行此操作取决于您选择的数据库(您没有提及)。


0
投票
SELECT t1.a, t1.b, t1.c, t1.mycol, t2.value
FROM t1
INNER JOIN t2 ON t1.a=t2.a AND t1.b=t2.b;

另一个简单地根据 t1 连接所有记录的选项:

SELECT t1.a, t1.b, t1.c, t1.mycol, t2.value
FROM t1
LEFT JOIN t2 ON t1.pk=t2.pk;

0
投票

嗯 - 我通过“加入后备表”来到这里,在更技术性的背景(流量)中寻找有点类似的挑战。就我而言,受此启发的(谢谢大家:-))解决方案可能看起来有点复杂,但唯一正确的解决方案(待定)。抱歉,我会稍微重写(简化?)模型。关键是,您需要一种基于可为空键的“唯一查找”。好的,我的“处理程序”映射是一个“元信息”(准静态查找),在 3 维(不完整矩阵)上具有“权重”(分析信息)。这实际上比OP多了一个,但它显示了方向......对于查找表,您当然希望它有一个主键。但是你只能有一个(部分)唯一键,因为维度是可以为空的(**即将到来?对此的特别评论,避免了退化的零键造成的混乱)。您从一开始就应该有单独的查找表!至少我相信,我的分析师会更好地管理:为我提供(在我的情况下数百万)元数据“包括后备”,并为所有组合代码继承提供主要跳到第 49 行(待定):“不,而是分开的......”

    drop schema if exists fallback_join cascade;
create schema fallback_join;
set search_path to fallback_join;

/*
-- https://stackoverflow.com/questions/63702857/sql-join-when-column-is-available-else-join-with-remaining-columns
T1 :
+---+---+---+-------+
| a | b | c | mycol |
+---+---+---+-------+
| 1 | 2 | 3 | john  |
| 1 | 3 | 4 | cena  |
+---+---+---+-------+
*/
create table trips_weighable( -- just like Informants in the OP, sorry for the renaming.
 a integer,
 b integer,
 c integer,
 name text,
 primary key(name) -- assumably, but not necessary
);
insert into trips_weighable(a,b,c,name) values
    (1,2,3,'john'),
    (1,2,4,'cena');
/* deprecated
T2:
+---+---+---+-------+
| a | b | c | value |
+---+---+---+-------+
| 1 | 2 | 3 |    10 |
| 1 | 3 |   |    20 |
+---+---+---+-------+

create table trips_weights(
 a integer,
 b integer,
 c integer,
 value integer,
-- primary key(?name) -- nope, because NULLABLE, however, we will overcome this, see (*) below
 unique (a,b,c)
);
insert into trips_weights(a,b,c,value) values
(1,2,3,10),
(1,2,null,20);
-- nope, rather separate weights_fallback({x}), x in {abc} - all(almost?) combinations 
CREATE VIEW trips_weights_abc AS
 SELECT * FROM trips_weights WHERE a IS NOT NULL AND  b IS NOT NULL AND c IS NOT NULL;
-- ... as a workaround, if it just comes like that, but
-- i rather expect my analyst to "know" whether some "weight" data is fallback on one or more keys:
*/ -- "normal weights"
CREATE TABLE trips_weights_abc(
    a integer,
    b integer,
    c integer,
    value integer,
    primary key(a,b,c)
--  unique (a,b,c) -- nope, we have something better now
);
insert into trips_weights_abc(a,b,c,value) values
    (1,2,3,10);

/* deprecated
CREATE VIEW trips_weights_ab AS
 SELECT * FROM trips_weights WHERE a IS NOT NULL AND  b IS NOT NULL;
*/
CREATE TABLE trips_weights_ab(
    a integer,
    b integer,
--! c integer,
    value integer,
    primary key(a,b) --wo/c
);
insert into trips_weights_ab(a,b,value) values
    (1,2,20);

CREATE VIEW trips_weighed AS
    SELECT t.*,wabc.value wabc,wab.value AS wab,
    --, util.some_fallback_functionality1(wabc,wab,wac,wbc,wa,wb,wc,w(?)), e.g.
    COALESCE(wabc.value,wab.value)
    FROM trips_weighable t
    LEFT JOIN trips_weights_abc wabc ON wabc.a = t.a AND wabc.b = t.b AND wabc.c = t.c 
    LEFT JOIN trips_weights_ab wab ON wab.a = t.a AND wab.b = t.b 
;
select * from trips_weighed;
/*
 a | b | c | name | wabc | wab | coalesce 
---+---+---+------+------+-----+----------
 1 | 2 | 3 | john |   10 |  20 |       10
 1 | 2 | 4 | cena |      |  20 |       20
*/
© www.soinside.com 2019 - 2024. All rights reserved.