SQL 中的 LEFT JOIN 但不包括连接 where table1.column1 = 'specific_value'

Posted

技术标签:

【中文标题】SQL 中的 LEFT JOIN 但不包括连接 where table1.column1 = \'specific_value\'【英文标题】:LEFT JOIN in SQL but exclude joining where table1.column1 = 'specific_value'SQL 中的 LEFT JOIN 但不包括连接 where table1.column1 = 'specific_value' 【发布时间】:2019-12-04 00:04:02 【问题描述】:

我正在尝试加入 2 个几乎 1:1 的数据集。 table1segment1 上进行分段,以便指标在该段的可能值之间进行拆分,如下所示。

| attribute1 | attribute2 | segment1 | metric1           | metric2           |
|------------|------------|----------|-------------------|-------------------|
| bob        | 3          | home     | 1/3 total metric1 | 1/5 total metric2 |
| bob        | 3          | work     | 2/3 total metric1 | 4/5 total metric2 |
| ray        | 5          | home     | 1/3 total metric1 | 1/5 total metric2 |
| ray        | 5          | work     | 2/3 total metric1 | 4/5 total metric2 |

table2未分段,如下:

| attribute1 | attribute2 | metric3       | metric4       |
|------------|------------|---------------|---------------|
| bob        | 3          | total metric3 | total metric4 |
| ray        | 5          | total metric3 | total metric4 |

常规的LEFT JOIN 会导致与table2 重复的行,因为table2 行连接到每个table1.segment1 可能性。所以metric3metric4 被重复计算。我对JOIN 没有其他常见限制。

| attribute1 | attribute2 | segment1 | metric1           | metric2           | metric3       | metric4       |
|------------|------------|----------|-------------------|-------------------|---------------|---------------|
| bob        | 3          | home     | 1/3 total metric1 | 1/5 total metric2 | total metric3 | total metric4 |
| bob        | 3          | work     | 2/3 total metric1 | 4/5 total metric2 | total metric3 | total metric4 |
| ray        | 5          | home     | 1/3 total metric1 | 1/5 total metric2 | total metric3 | total metric4 |
| ray        | 5          | work     | 2/3 total metric1 | 4/5 total metric2 | total metric3 | total metric4 |

我认为一种解决方法是找到一种方法来跳过除 table1.segment1 字段的 1 个可能值之外的所有可能值的连接操作。对于table1 的其他部分,table2 列将是NULL,但现在还可以。

我的方法是在JOIN 子句中使用CASE 语句,如下所示:

select
    table1.attribute1,
    table1.attribute2,
    table1.segment1,
    table1.metric1,
    table1.metric2,
    table2.metric3,
    table2.metric4
from table1
left join table2
    on table1.attribute1 = table2.attribute1
    and table1.attribute2 = table2.attribute2
    and CASE
            WHEN table1.segment1 = 'home' then TRUE
            ELSE FALSE
        END

这是 Redshift 上的有效 SQL。如果有更好的方法,任何人都可以验证这是否可行?我正在对数据进行质量检查,但速度很慢,我需要双重确认。

此外,这将假设segment1 的每一种可能性都存在于table1 中,对每条记录,对吧?否则我可能会过滤掉table2 行?

预期(但可能不是最好的)结果:

| attribute1 | attribute2 | segment1 | metric1           | metric2           | metric3       | metric4       |
|------------|------------|----------|-------------------|-------------------|---------------|---------------|
| bob        | 3          | home     | 1/3 total metric1 | 1/5 total metric2 | total metric3 | total metric4 |
| bob        | 3          | work     | 2/3 total metric1 | 4/5 total metric2 | NULL          | NULL          |
| ray        | 5          | home     | 1/3 total metric1 | 1/5 total metric2 | total metric3 | total metric4 |
| ray        | 5          | work     | 2/3 total metric1 | 4/5 total metric2 | NULL          | NULL          |

【问题讨论】:

您没有清楚地描述所需的输出是输入的函数。你只是对你想要或得到的东西进行零散的部分描述。使用足够多的单词、句子和对部分示例的引用来清楚完整地表达你的意思。在给出业务关系(船舶)/关联或表(基础或查询结果)时,说明其中的一行根据其列值说明了业务情况。 PS 了解 LEFT JOIN ON 返回什么: INNER JOIN ON rows UNION ALL 不匹配的左表行,由 NULL 扩展。作为 OUTER JOIN 的一部分,始终知道您想要什么 INNER JOIN。 PSminimal reproducible example 【参考方案1】:

如果我理解正确,你可以使用row_number()

select t1.*, t2.*
from (select t1.*,
             row_number() over (partition by attribute1, attribute2 order by attribute1) as seqnum
      from table1 t1
     ) t1 left join
     (select t2.*,
             row_number() over (partition by attribute1, attribute2 order by attribute1) as seqnum
      from table2 t2
     ) t2
     on t2.attribute1 = t1.attribute1 and
        t2.attribute2 = t1.attribute2 and
        t2.seqnum = t1.seqnum

【讨论】:

以上是关于SQL 中的 LEFT JOIN 但不包括连接 where table1.column1 = 'specific_value'的主要内容,如果未能解决你的问题,请参考以下文章