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

时间:2020-03-06 14:27:11  来源:igfitidea点击:

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

现在,我正在寻找特定section_id的所有条目,并且希望除了"从mod_a,mod_b,mod_c ... mod_xyzzy的其中选择section_id = value的地方选择*"以外,还有另一种方法……或者更糟糕的是,使用单独的查询每个模块。

解决方案

关于什么?

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

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

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

也许一些其他信息会有所帮助,但是听起来我们已经有了解决方案。我们将必须从所有带有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>

我们也可以将其打包为视图。
还要注意字段列表而不是*,如果我们打算实际使用*,我会建议我们这样做。

好吧,只有这么多种方法可以聚合来自多个表的信息。我们可以像在示例中提到的那样加入,也可以运行多个查询并将它们合并在一起,如borjab的回答中所述。我不知道创建一个与所有模块表相交的表的想法对我们是否有用,但是如果section_id在这样的表上,我们将能够从单个查询中获取所有信息。否则,我为懒惰鼓掌,但恐怕要说,我看不出有什么方法可以使工作更轻松:)

如果表随时间变化,则可以在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 '

我有两个建议。

  • 也许我们需要合并所有表。如果它们都包含相同的结构,那么为什么不拥有一个"主"模块表,而只需添加一个新列来标识该模块(" A"," B"," C"等)。大部分都是相同的,但是我们有一些不同的列,我们仍然可以将所有通用信息合并到一个表中,并保留具有这些差异的较小的模块特定表。然后,我们只需要对它们进行联接。此建议假定我们对我们提到的section_id列的查询是非常关键的,因此快速查找。通过一个查询,我们可以获得所有通用信息,而在第二查询中,如果需要,我们将获得任何特定信息。 (而且我们可能没有,例如,如果我们尝试验证该节的exenseense,那么在公共表中找到它就足够了)
  • 或者,我们可以添加另一个表,该表将section_id映射到它们所在的模块。
section_id | module
-----------+-------
      1    |  A
      2    |  B
      3    |  A
     ...   | ...

这确实意味着我们必须运行两个查询,一个查询针对此映射表,另一个查询针对模块表,以提取任何有用的数据。如果需要查找所有模块共有的其他列,则可以使用其他列和这些列的索引来扩展此表。此方法有一定的缺点,即数据是重复的。

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

数据库方面的一种选择是创建各种表的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;