【问题标题】:How do I do a join in SQL based on table name?如何根据表名在 SQL 中进行联接?
【发布时间】:2010-09-26 02:57:39
【问题描述】:

好的,所以我们有一堆这样命名的表:

training_data_001
training_data_002
training_data_003
training_data_004
training_data_005

然后要找到我们在另一个表中查看字段的那些,我们将其命名为 master.training_type。

无论如何,我想知道是否有人知道一种方法可以对这种数据进行基于奇怪表名的连接。像这样的:

SELECT foo FROM master WHERE id = ? 
INNER JOIN training_data_${master.training_type}
ON foo.id = training_data_${master.training_type}.foo_id

我知道我可以在客户端执行此操作,但最好让数据库执行此操作。

另请注意:它是 SQL Server。

更新:我决定只在客户端进行。还是谢谢大家。

谢谢!

-fREW

【问题讨论】:

  • WHERE 子句出现在所有 JOIN 之后

标签: sql syntax join


【解决方案1】:

分区视图是一种可能的方法。由于您只选择 foo 列,您真的只是通过 INNER JOIN 检查训练表中是否存在一行?此外,您似乎正在尝试在联接中使用 foo 作为别名,但在您的 SELECT 子句中没有以这种方式设置。结果,我在这里猜测您真正想要什么。

另一个问题...训练表集是静态的吗?您是否希望能够添加具有新后缀编号的新表并使其正常工作?

另一种可能的解决方案:

SELECT
     foo
FROM
     dbo.master m
WHERE
     (training_type = '001' AND EXISTS (SELECT * FROM dbo.training_data_001 WHERE foo_id = m.id)) OR
     (training_type = '002' AND EXISTS (SELECT * FROM dbo.training_data_002 WHERE foo_id = m.id)) OR
     (training_type = '003' AND EXISTS (SELECT * FROM dbo.training_data_003 WHERE foo_id = m.id)) OR
     (training_type = '004' AND EXISTS (SELECT * FROM dbo.training_data_004 WHERE foo_id = m.id)) OR
     (training_type = '005' AND EXISTS (SELECT * FROM dbo.training_data_005 WHERE foo_id = m.id))

如果你真的想从训练数据表中返回列,那么你可以使用类似的东西:

SELECT
     m.id,
     COALESCE(t1.my_col, t2.my_col, t3.my_col, t4.my_col, t5.my_col) AS my_col
FROM
     dbo.master m
LEFT OUTER JOIN dbo.training_data_001 t1 ON m.training_type = '001' AND t1.foo_id = m.id
LEFT OUTER JOIN dbo.training_data_002 t1 ON m.training_type = '002' AND t2.foo_id = m.id
LEFT OUTER JOIN dbo.training_data_003 t1 ON m.training_type = '003' AND t3.foo_id = m.id
LEFT OUTER JOIN dbo.training_data_004 t1 ON m.training_type = '004' AND t4.foo_id = m.id
LEFT OUTER JOIN dbo.training_data_005 t1 ON m.training_type = '005' AND t5.foo_id = m.id

【讨论】:

    【解决方案2】:

    做这样的事情:

    create view training_data_all as
    select '001' as training_type, * from training_data_001
    union all
    select '002' as training_type, * from training_data_002
    union all
    select '003' as training_type, * from training_data_003
    union all
    select '004' as training_type, * from training_data_004
    union all
    select '005' as training_type, * from training_data_005
    

    然后只需选择并加入到/从它:

    SELECT foo FROM master WHERE id = ? 
    INNER JOIN training_data_all
    ON foo.id = training_data_all.foo_id
    WHERE training_data_all.training_type = ${master.training_type}
    

    如果表列表随着时间的推移而增长/缩小,您可以通过对系统表进行一些查找来根据存在的表动态编写相同的视图。

    但这些都不是很有效。您能以某个固定的时间间隔将这些数据 ETL 到一个组合表中吗?

    【讨论】:

      【解决方案3】:

      如果表都是相同的结构,则在表之间创建一个Partitioned View 并连接到视图。您需要对列(可能是日期)进行检查约束,以便查询优化器可以进行分区消除。

      【讨论】:

        【解决方案4】:

        您只能在存储过程中使用动态 SQL 来执行此操作。如果您出于安全或其他原因不想即时执行,也可以通过代码生成提前生成视图或存储过程。

        【讨论】:

          【解决方案5】:

          您只能使用动态 SQL 来读取 master.training_type 以构建一个字符串,然后使用 EXEC (@stringvar) 执行该字符串

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-11-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-05-21
            • 1970-01-01
            相关资源
            最近更新 更多