【问题标题】:how do I query multiple SQL tables for a specific key-value pair?如何查询多个 SQL 表以获取特定的键值对?
【发布时间】:2008-09-19 18:17:47
【问题描述】:

情况:具有多个可安装模块的 PHP 应用程序在数据库中为每个模块创建一个新表,样式为 mod_A、mod_B、mod_C 等。每个都有列 section_id。

现在,我正在寻找特定 section_id 的所有条目,我希望除了“Select * from mod_a, mod_b, mod_c ... mod_xyzzy where section_id=value”之外还有另一种方法......甚至更糟,对每个模块使用单独的查询。

【问题讨论】:

    标签: sql lazy-evaluation


    【解决方案1】:

    如果表格随时间变化,您可以在 SP 中内联代码生成您的解决方案(伪代码 - 您必须填写):

    SET @sql = ''
    
    DECLARE CURSOR FOR
    SELECT t.[name] AS TABLE_NAME
    FROM sys.tables t
    WHERE t.[name] LIKE 'SOME_PATTERN_TO_IDENTIFY_THE_TABLES'
    

    --或者这个

    DECLARE CURSOR FOR
    SELECT t.[name] AS TABLE_NAME
    FROM TABLE_OF_TABLES_TO_SEACRH t
    
    START LOOP
    
    IF @sql <> '' SET @sql = @sql + 'UNION ALL '
    SET @sql = 'SELECT * FROM [' + @TABLE_NAME + '] WHERE section_id=value '
    
    END LOOP
    
    EXEC(@sql)
    

    我偶尔会使用这种技术,当时没有任何明显的方法可以让它在没有动态 SQL 的情况下适应未来。

    注意:在您的循环中,您可以使用 COALESCE/NULL 传播技巧,并在循环之前将字符串保留为 NULL,但如果您不熟悉该习语,则不清楚:

    SET @sql = COALESCE(@sql + ' UNION ALL ', '')
        + 'SELECT * FROM [' + @TABLE_NAME + '] WHERE section_id=value '
    

    【讨论】:

    • 优秀。模块表使用 mod_A_settings 的命名模式。因此,如果在一个有 16 个页面的站点上,有 50 个模块实例(例如,模块 foostatistics,具有不同的配置值),则 mod_foostatistics_settings 上将有 50 行,其中行指向特定的 section_id:s跨度>
    【解决方案2】:

    怎么样?

    SELECT * FROM mod_a WHERE section_id=value
    UNION ALL
    SELECT * FROM mod_b WHERE section_id=value
    UNION ALL
    SELECT * FROM mod_c WHERE section_id=value
    

    【讨论】:

      【解决方案3】:

      我有两个建议。

      1. 也许您需要整合所有表格。如果它们都包含相同的结构,那么为什么不拥有一个“主”模块表,它只是添加一个标识模块的新列(“A”、“B”、“C”……)

        如果您的模块表大体相同,但有几列不同,您仍然可以将所有常见信息合并到一个表中,并保留具有这些差异的较小的模块特定表。然后你只需要加入他们。

        此建议假定您对您提到的 section_id 列的查询对于快速查找非常关键。通过一次查询,您可以获得所有常见信息,如果需要,您可以通过第二次查询获得任何特定信息。 (而且您可能不会——例如,如果您试图验证该部分的存在性,那么在公用表中找到它就足够了)

      2. 或者,您可以添加另一个表,将 section_id 映射到它们所在的模块。

        section_id |模块 -----------+-------- 1 |一种 2 |乙 3 |一种 ... | ...

        这确实意味着您必须运行两个查询,一个针对此映射表,另一个针对模块表以提取任何有用的数据。

        如果您需要查找所有模块共有的其他列,您可以使用其他列和这些列上的索引来扩展此表。

        这种方法有一定的缺点,就是数据重复。

      【讨论】:

      • 这有点超出了问题的范围,但我确实喜欢将通用模块数据合并到一个表中的想法。
      【解决方案4】:

      也许一些额外的信息会有所帮助,但听起来您已经有了解决方案。您必须从所有带有 section_id 的表中进行选择。您可以使用连接而不是表列表,在 section_id 上连接。例如

      select a.some_field, b.some_field.... 
      from mod_a a
      inner join mod_b b on a.section_id = b.section_id
      ...
      where a.section_id = <parameter>
      

      您也可以将其打包为视图。 还要注意字段列表而不是 *,如果您打算实际使用 *,我会推荐它。

      【讨论】:

        【解决方案5】:

        嗯,从多个表中聚合信息的方法只有这么多。您可以加入,就像您在示例中提到的那样,或者您可以运行多个查询并将它们联合在一起,如 borjab 的答案。我不知道创建一个与所有模块表相交的表的想法是否对您有用,但如果 section_id 在这样的表上,您将能够从单个查询中获取所有内容。否则,我为你的懒惰喝彩,但我不敢说,我看不出有什么办法可以让这份工作变得更轻松:)

        【讨论】:

          【解决方案6】:

          我打算提出与 borjab 相同的想法。唯一的问题是,如果添加另一个表,则必须更新所有这些查询。我看到的唯一其他选项是存储过程。

          我确实想到了另一种选择,或者至少是一种更简单的呈现方式。您还可以对这些多个表使用视图以使它们显示为一个,然后您的查询将看起来更清晰,更易于理解,并且当您想对这些表执行其他查询时,您不必重写长联合查询多个表。

          【讨论】:

            【解决方案7】:
            SELECT * FROM (
                SELECT * FROM table1
                UNION ALL
                SELECT * FROM table2
                UNION ALL
                SELECT * FROM table3
            ) subQry
            WHERE field=value
            

            【讨论】:

            • 在“来自 table10 ...来自 table 100 ...来自 table NI”上失败。我的意思是,没有那么多模块,(只有大约 60 个左右),但仍然......
            【解决方案8】:

            数据库方面的一个选项是创建各种表的 UNION ALL 视图。添加表格时,您需要将其添加到视图中,否则它看起来就像一个单独的表格。

            CREATE VIEW modules AS (
                SELECT * FROM mod_A
                UNION ALL 
                SELECT * FROM mod_B
                UNION ALL 
                SELECT * FROM mod_C
            );
            
            select * from modules where section_id=value;
            

            【讨论】:

            • 人们应该小心这样的视图,因为根据风格,如果对其应用任何类型的条件,它们可能会遇到一些性能瓶颈。我肯定知道 MySQL,在这样的视图上使用 WHERE 子句将无法使用任何基础表的索引,并且会导致创建临时表。还有……帽子。
            猜你喜欢
            • 1970-01-01
            • 2022-01-12
            • 1970-01-01
            • 2014-01-23
            • 1970-01-01
            • 1970-01-01
            • 2013-06-10
            • 2016-09-16
            • 2014-02-13
            相关资源
            最近更新 更多