【问题标题】:Dynamic or conditional Join动态或条件连接
【发布时间】:2015-11-08 13:51:03
【问题描述】:

是否可以使用 SQL(或 PL/SQL)动态连接表?

我有一个包含多列的 TableA。下面的每一列都有自己单独的表,除了 id。

|  id | AA | BB | CC | DD | EE |
|-----|----|----|----|----|----|
| 123 |  0 |  0 |  1 |  1 |  1 |
| 456 |  1 |  1 |  0 |  1 |  1 |
| 789 |  1 |  0 |  1 |  0 |  0 |
.......

基于我需要连接表的列的值。

  • 对于 id = 123,我想加入 CCDDEE 表。李>
  • id = 456我想加入AABBDD EE 表。
  • 对于 id = 789,我想加入 AACC 表。
  • 等等。
  • 最后将结果合并到一个表中。
  • 还有表 AABBCCDDEE具有相同的列集。

示例数据:

AA

|  id | Value |
|-----|-------|
| 456 |   bbb |
| 789 |   ccc |

BB

|  id | Value |
|-----|-------|
| 789 |   ccc |
| 456 |   bbb |

抄送

|  id | Value |
|-----|-------|
| 123 |   aaa |
| 789 |   ccc |

DD

|  id | Value |
|-----|-------|
| 123 |   aaa |

EE

|  id | Value |
|-----|-------|
| 123 |   aaa |

预期输出

|  id | Value |
|-----|-------|
| 123 |   abc |
| 789 |   ccc |

id 456 不会成为最终结果的一部分,因为它会在加入时被过滤掉。

是否可以在 SQL 或 PL/SQL 中执行此操作(首选纯 SQL)。另外:我想做一个INNER JOIN

【问题讨论】:

  • 您应该使用示例数据所需的结果来编辑您的查询。
  • 值后面加句号的原因是什么?您可以为表格发布 DDL 吗?
  • 那是错字。更新了问题
  • 假设,可以动态地JOIN(事实并非如此):鉴于表 AAEE 执行 - 根据您的描述-“具有相同的列集”并且您想“最终将结果合并到一个大选项卡中”-个人加入会是什么样子?为了UNION 他们,您不能每次都选择所有表的所有列,根据您的示例,表(以及列)的数量可能不同 - 而 UNION 中的所有 SELECTs 必须具有相同的列数。 -- 表格结构、样本数据和预期输出可能有助于找到解决方案...
  • 编辑您的问题并提供示例数据所需的结果。目前尚不清楚您要做什么。

标签: sql join plsql oracle11g


【解决方案1】:

您加入所有表并取出您需要的列。请注意,SQL 查询定义了一组固定用于所有行的列。所以,“有条件地”加入一个表并没有什么意义。你打算在哪里使用这些列?

为了你的目的你想要left join:

select <columns that you want>
from table t left join
     students s
     on . . . left join
     classes c
     on . . . left join
     . . .

编辑:

您修改后的问题非常不同,应该是另一个问题。但是,我认为这可以满足您的要求:

select
from a join
     (select 1 as aa, 0 as bb, 0 as cc, 0 as dd, 0 as ee, id, value from aa union all
      select 0 as aa, 1 as bb, 0 as cc, 0 as dd, 0 as ee, id, value from bb union all
      select 0 as aa, 0 as bb, 1 as cc, 0 as dd, 0 as ee, id, value from cc union all
      select 0 as aa, 0 as bb, 0 as cc, 1 as dd, 0 as ee, id, value from dd union all
      select 0 as aa, 0 as bb, 0 as cc, 0 as dd, 1 as ee, id, value from ee 
     ) o
     on a.id = o.id and
        a.aa = o.aa and a.bb = o.bb and a.cc = o.cc and a.dd = o.dd and a.ee = o.ee;

【讨论】:

  • 左连接不起作用。我已将问题更新为更清楚
  • 感谢您的回复。我会试试这个。但是,具有 1 和 0 的表是实际表的一小部分。实际的表格将包含更多的行和组合
  • @ZAKB 。 . .只能回答您提出的问题。如果您有不同的问题,则应将其作为不同的问题提出。
【解决方案2】:

TableA 和表 AAEEJOIN 请求(以及所有这些 UNIONed up)应该可能看起来类似于

的输出
WITH
TableAUnpivot AS (
  SELECT
    id
    , tableName
  --  , value
  FROM
    TableA UNPIVOT EXCLUDE NULLS
      (VALUE FOR(tableName) IN ( "AA", "BB", "CC", "DD", "EE")
      )
),
DataTablesCombined AS (
  SELECT 'AA' tableName, id, value FROM AA UNION ALL
  SELECT 'BB', id, value FROM BB UNION ALL
  SELECT 'CC', id, value FROM CC UNION ALL
  SELECT 'DD', id, value FROM DD UNION ALL
  SELECT 'EE', id, value FROM EE
),
ReadyForJoin AS (
  SELECT
    id
    , tableName
    , value
  FROM TableAUnpivot
  JOIN DataTablesCombined
    USING (tableName, id)
),
LookLikeAJoin AS (
  SELECT
    *
  FROM ReadyForJoin
  PIVOT (MIN(value) FOR tableName
         IN ('AA' AS AA, 'BB' AS BB, 'CC' AS CC, 'DD' AS DD, 'EE' AS EE))
)
SELECT
  * FROM LookLikeAJoin ORDER BY id
;

样本数据是什么

|  ID |     AA |     BB |     CC |     DD |     EE |
|-----|--------|--------|--------|--------|--------|
| 123 | (null) | (null) |    aaa |    aaa |    aaa |
| 456 |    bbb |    bbb | (null) | (null) | (null) |
| 789 |    ccc | (null) |    ccc | (null) | (null) |

其中一个单元格不同于 NULL,当且仅当:

  • 已在TableA中设置1,并且
  • AAEE 的各个表中分配了一个值。

注意:为了让这一切正常工作,TableA 中的所有 0 都必须是 NULLified .

前提是,这走向了正确的方向:如何从这里继续?

最直接的方法似乎是将最终的SELECT替换为

SELECT
  id, COALESCE(aa, bb, cc, dd, ee) value FROM LookLikeAJoin WHERE id != 456 ORDER BY id
;

(鉴于,123abc 是一个错字...)

查看上述内容:SQL Fiddle

如果需要调整/进一步详细信息,请发表评论。

【讨论】:

  • 非常感谢!!你对要求很满意,看起来这会很好。我将进一步对此进行测试,并让您知道是否还需要其他任何东西。再次感谢
猜你喜欢
  • 2018-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 2018-01-10
相关资源
最近更新 更多