【问题标题】:Joining three table levels by single key通过单个键连接三个表级别
【发布时间】:2020-01-17 14:59:18
【问题描述】:

场景:我有 3 张桌子(高级、中级和低级)。 Higher 表中的每个项目都可以包含中间表中的多行项目。下层表可以包含聚合值,这些值连接到上层表的每个项目。

逻辑:目的是将中间表的每一行聚合到上层表中(全连接),然后对这些行聚合下层表的项目。所有三个表共享 keyA 列。

+-----+------------+-------------+--------------+
| keyA | HigherName | HigherValue | HigherStatus |
+-----+------------+-------------+--------------+
| 123 | Item1      | 100         | Active       |
+-----+------------+-------------+--------------+
| 124 | Item2      | 105         | Inactive     |
+-----+------------+-------------+--------------+
| 125 | Item3      | 96          | Inactive     |
+-----+------------+-------------+--------------+
| 126 | Item4      | 104         | Inactive     |
+-----+------------+-------------+--------------+
| 127 | Item5      | 89          | Active       |
+-----+------------+-------------+--------------+
| 128 | Item6      | 97          | Inactive     |
+-----+------------+-------------+--------------+

EX 中桌:

+-----+---------+----------+
| keyA | MidName | MidValue |
+-----+---------+----------+
| 123 | Mid1    | 55       |
+-----+---------+----------+
| 123 | Mid2    | 46       |
+-----+---------+----------+
| 123 | Mid3    | 49       |
+-----+---------+----------+
| 124 | Stat1   | 41       |
+-----+---------+----------+
| 124 | Stat2   | 59       |
+-----+---------+----------+
| 124 | Stat3   | 51       |
+-----+---------+----------+
| 125 | Gen1    | 56       |
+-----+---------+----------+
| 125 | Gen2    | 57       |
+-----+---------+----------+
| 126 | Test1   | 44       |
+-----+---------+----------+
| 127 | Lev1    | 42       |
+-----+---------+----------+
| 127 | Lev2    | 49       |
+-----+---------+----------+
| 127 | Lev3    | 50       |
+-----+---------+----------+
| 127 | Lev4    | 60       |
+-----+---------+----------+
| 128 | Spec1   | 61       |
+-----+---------+----------+
| 128 | Spec2   | 39       |
+-----+---------+----------+

EX 下桌:

+-----+-----------+------------+
| keyA | LowerName | LowerValue |
+-----+-----------+------------+
| 123 | Sub1      | 12         |
+-----+-----------+------------+
| 123 | Sub1      | 14         |
+-----+-----------+------------+
| 123 | Sub1      | 13         |
+-----+-----------+------------+
| 124 | Sub2      | 13         |
+-----+-----------+------------+
| 124 | Sub2      | 10         |
+-----+-----------+------------+
| 124 | Sub2      | 11         |
+-----+-----------+------------+
| 125 | Sub3      | 19         |
+-----+-----------+------------+
| 125 | Sub3      | 14         |
+-----+-----------+------------+
| 126 | Sub4      | 15         |
+-----+-----------+------------+
| 127 | Sub5      | 14         |
+-----+-----------+------------+
| 127 | Sub5      | 13         |
+-----+-----------+------------+
| 127 | Sub5      | 11         |
+-----+-----------+------------+
| 127 | Sub5      | 10         |
+-----+-----------+------------+
| 128 | Sub6      | 11         |
+-----+-----------+------------+
| 128 | Sub6      | 12         |
+-----+-----------+------------+

EX 输出:

+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| keyA | HigherName | HigherValue | HigherStatus | MidName | MidValue | LowerName | LowerValue |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 123 | Item1      | 100         | Active       | Mid1    | 55       | Sub1      | 12         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 123 | Item1      | 100         | Active       | Mid2    | 46       | Sub1      | 14         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 123 | Item1      | 100         | Active       | Mid3    | 49       | Sub1      | 13         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 124 | Item2      | 105         | Inactive     | Stat1   | 41       | Sub2      | 13         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 124 | Item2      | 105         | Inactive     | Stat2   | 59       | Sub2      | 10         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 124 | Item2      | 105         | Inactive     | Stat3   | 51       | Sub2      | 11         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 125 | Item3      | 96          | Inactive     | Gen1    | 56       | Sub3      | 19         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 125 | Item3      | 96          | Inactive     | Gen2    | 57       | Sub3      | 14         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 126 | Item4      | 104         | Inactive     | Test1   | 44       | Sub4      | 15         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 127 | Item5      | 89          | Active       | Lev1    | 42       | Sub5      | 14         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 127 | Item5      | 89          | Active       | Lev2    | 49       | Sub5      | 13         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 127 | Item5      | 89          | Active       | Lev3    | 50       | Sub5      | 11         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 127 | Item5      | 89          | Active       | Lev4    | 60       | Sub5      | 10         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 128 | Item6      | 97          | Inactive     | Spec1   | 61       | Sub6      | 11         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+
| 128 | Item6      | 97          | Inactive     | Spec2   | 39       | Sub6      | 12         |
+-----+------------+-------------+--------------+---------+----------+-----------+------------+

我做了什么:我试图使用完全连接来组合表格。当在高和中使用完全连接时,一切正常。但是当我尝试包含 Lower 时,我得到了错误:

'databaseA.higher.keyA' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

问题:我做错了什么,如何解决?

到目前为止的代码:

Select 
    [keyA ] = databaseA.higher.keyA,
    [Higher Name ] = databaseA.higher.higher_name,
    [Higher Value ] = databaseA.higher.higher_value,
    [Higher Status ] = databaseA.higher.higher_status,
    [Mid Name ] = databaseA.mid.mid_status,
    [Mid Value ] = databaseA.mid.mid_value,
    [Lower Name ] = databaseA.lowerA.LowerA_status,
    [Lower Value ] = databaseA.lowerA.lowerA_value
from databaseA.higher
FULL JOIN databaseA.mid
    on databaseA.higher.keyA = databaseA.mid.keyA
Full JOIN databaseA.lower
    on databaseA.higher.keyA = databaseA.lower.keyA
where databaseA.higher.keyA in ('82487')

【问题讨论】:

  • 请说明合并表格的逻辑,并添加数据库标签。
  • 该查询包含多个错误。而且还是不能给出描述的错误信息。
  • FULL JOIN databaseA.mid on databaseA.higher.keyA = databaseA.higher.keyA.keyA INNER JOIN databaseA.mid on databaseA.higher.keyA = databaseA.mid.keyA 您将加入mid 表2 次。 FULL JOIN 仅使用 higher.keyA。我认为这是错误的databaseA.higher.keyA.keyA。请帮助我们进一步了解。
  • @GordonLinoff 添加到问题中。逻辑基本上是基于keyA的三个表的全连接。
  • @jarlh 修正了 OP 中的一些错误。

标签: sql database tsql join


【解决方案1】:

给你:

select
  h.*,
  x.midname, x.midvalue, x.lowername, x.lowervalue
from higher h
left join (
  select 
    coalesce(a.keya, b.keya) as keya,
    a.midname, a.midvalue, b.lowername, b.lowervalue
  from (
    select *,
      row_number() over(partition by keya order by midname) as rn
    from mid
  ) a
  full outer join (
    select *,
      row_number() over(partition by keya order by lowername) as rn
    from lower
  ) b on a.keya = b.keya and a.rn = b.rn
) x on h.keya = x.keya

您需要使用人工键连接中表和下表(我添加了rn 列)。然后将更高的表与前一个结果集连接起来。

【讨论】:

  • 非常感谢,我现在测试一下。两个问题:这里的coalesce有什么作用?为什么我不能使用 keyA 进行映射?
  • COALESCE() 是必要的,因为您正在进行完全外部连接。如果中间和下面的行数不匹配(假设中间有 3 行,下面有 5 行),那么其中一个键可能为空。如果您的行数始终相同,则没有必要。
  • 到第二个问题。如果中间有 3 行,下部有 3 行,则通过 keya 连接将产生 9 行。但是您只想要 3。这就是为什么您需要通过人工键 (keya, rn) 加入的原因,我在其中创建了 rn 作为简单的行号。
  • 非常感谢,我明白了。最后一个问题:如果lower和higher的值可以直接连接(因为所发生的情况是对于与其相连的mid的每一列都将重复相同的higher/lower值),那么在两者之间进行映射会更好吗?越来越高,然后将它们映射到中间?
  • @DGMS89 不完全确定。它可能取决于中表和低表的可空性和基数。你总是在中下排吗?你总是在中间和下面有相同数量的行吗?答案可能取决于真实数据的布局方式。
猜你喜欢
  • 2020-12-10
  • 2013-07-03
  • 1970-01-01
  • 2020-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-14
  • 2016-07-04
相关资源
最近更新 更多