как мне запросить несколько таблиц SQL для определенной пары ключ-значение?

StackOverflow https://stackoverflow.com/questions/104230

  •  01-07-2019
  •  | 
  •  

Вопрос

Ситуация:PHP-приложение с несколькими устанавливаемыми модулями создает новую таблицу в базе данных для каждого из них в стиле mod_A, mod_B, mod_C и т.д.Каждый из них имеет столбец section_id.

Теперь я ищу все записи для определенного section_id, и я надеюсь, что есть другой способ, кроме "Выбрать * из mod_a, mod_b, mod_c ...mod_xyzzy, где 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 '

Другие советы

О чем это?

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. Возможно, вам нужно объединить все ваши таблицы.Если все они содержат одинаковую структуру, то почему бы не иметь одну таблицу модулей "master", которая просто добавляет один новый столбец, идентифицирующий модуль ("A", "B", "C", ....)

    Если таблицы вашего модуля в основном одинаковы, но у вас есть несколько разных столбцов, вы все равно можете объединить всю общую информацию в одну таблицу и сохранить таблицы меньшего размера, относящиеся к конкретному модулю, с этими различиями.Тогда вам просто нужно было бы выполнить для них объединение.

    Это предложение предполагает, что ваш запрос к указанному вами столбцу section_id является сверхкритичным для быстрого поиска.С помощью одного запроса вы получите всю общую информацию, а со вторым вы получите любую конкретную информацию, если она вам понадобится.(А вы могли бы и не проверять - например, если бы вы пытались проверить существование раздела, тогда было бы достаточно найти его в общей таблице)

  2. В качестве альтернативы вы можете добавить другую таблицу, которая сопоставляет section_id с модулями, в которых они находятся.

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

    Однако это означает, что вам нужно выполнить два запроса, один к этой таблице сопоставления, а другой к таблице модуля, чтобы извлечь любые полезные данные.

    Вы можете расширить эту таблицу другими столбцами и индексами в этих столбцах, если вам нужно найти другие столбцы, общие для всех модулей.

    Этот метод имеет определенный недостаток в том, что данные дублируются.

Возможно, какая-то дополнительная информация помогла бы, но, похоже, у вас уже есть решение.Вам нужно будет выбрать из всех таблиц с идентификатором 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>

Вы также могли бы упаковать это в виде представления.Также обратите внимание на список полей вместо *, который я бы рекомендовал, если бы вы действительно собирались использовать * .

Что ж, существует не так уж много способов агрегировать информацию из нескольких таблиц.Вы можете присоединиться, как вы упомянули в своем примере, или вы можете запустить несколько запросов и объединить их вместе, как в ответе борджаба.Я не знаю, была бы вам полезна какая-то идея создания таблицы, которая пересекает все таблицы модуля, но если бы section_id был в подобной таблице, вы смогли бы получить все из одного запроса.В остальном, я приветствую вашу лень, но, боюсь сказать, я не вижу никакого способа облегчить эту работу :)

Я собирался предложить ту же идею, что и борджаб.Единственная проблема с этим заключается в том, что вам придется обновлять все эти запросы, если вы добавите другую таблицу.Единственный другой вариант, который я вижу, - это хранимая процедура.

Я действительно подумал о другом варианте здесь, или, по крайней мере, о более простом способе представить это.Вы также можете использовать представление этих нескольких таблиц, чтобы они отображались как единое целое, и тогда ваш запрос выглядел бы чище, его было бы легче понять, и вам не пришлось бы переписывать длинный запрос объединения, когда вы хотели бы выполнить другие запросы к этим нескольким таблицам.

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

Вариантом со стороны базы данных было бы создать представление ОБЪЕДИНЕНИЯ ВСЕХ различных таблиц.Когда вы добавляете таблицу, вам нужно будет добавить ее в представление, но в противном случае она будет выглядеть как отдельная таблица.

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;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top