如何查询特定键值对的多个SQL表?

时间:2008-09-19 18:17:47

标签: sql lazy-evaluation

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

现在,我正在寻找特定section_id的所有条目,我希望除了“选择*来自mod_a,mod_b,mod_c ... mod_xyzzy where section_id = value”之外还有另一种方式......或者更糟糕的是,为每个模块使用单独的查询。

8 个答案:

答案 0 :(得分:1)

怎么样?

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

答案 1 :(得分: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 '

答案 2 :(得分:1)

我有两个建议。

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

    如果您的模块表大致相同,但是您有一些不同的列,您可能仍然可以将所有公共信息合并到一个表中,并保留较小的模块特定表以及这些差异。然后你只需要对它们进行连接。

    此建议假定您对提及的section section_id的查询对于快速查找非常关键。只需一个查询即可获得所有常用信息,如果需要,您可以获得任何特定信息。 (你可能没有 - 例如,如果你试图验证该部分的存在性,那么在公共表中找到它就足够了)

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

    section_id | module
    -----------+-------
          1    |  A
          2    |  B
          3    |  A
         ...   | ...
    

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

    如果需要查找所有模块通用的其他列,可以使用其他列和索引扩展此表。

    这种方法有明显的不利之处,即数据是重复的。

答案 3 :(得分:0)

我建议和borjab一样。唯一的问题是,如果添加另一个表,则必须更新所有这些查询。我看到的唯一其他选项是存储过程。

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

答案 4 :(得分:0)

也许一些额外的信息会有所帮助,但听起来你已经有了解决方案。您必须使用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 :(得分:0)

嗯,只有很多方法来聚合来自多个表的信息。您可以加入,就像您在示例中提到的那样,或者您可以运行多个查询并将它们组合在一起,就像在borjab的答案中一样。我不知道创建一个与所有模块表相交的表的想法是否对你有用,但是如果section_id在一个像这样的表上,你就可以从一个查询获得所有东西。否则,我赞美你的懒惰,但我不敢说,我认为没有办法让你的工作变得更好:)

答案 6 :(得分:0)

SELECT * FROM (
    SELECT * FROM table1
    UNION ALL
    SELECT * FROM table2
    UNION ALL
    SELECT * FROM table3
) subQry
WHERE field=value

答案 7 :(得分:0)

数据库端的选项是创建各种表的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;