Динамически выбирать данные из нескольких существующих таблиц

#sql #sql-server #tsql

#sql #sql-сервер #tsql

Вопрос:

У меня в базе данных есть таблицы «T1», которые разбиты по месяцам формы (таблица_082020, таблица_092020, таблица_102020). Каждая содержит несколько миллионов записей.

  ---- ---------- ------- 
| id | date     | value |
 ---- ---------- ------- 
| 1  | 20200816 | abc   |
 ---- ---------- ------- 
| 2  | 20200817 | xyz   |
 ---- ---------- ------- 
  
  ---- ---------- ------- 
| id | date     | value |
 ---- ---------- ------- 
| 1  | 20200901 | cba   |
 ---- ---------- ------- 
| 2  | 20200901 | zyx   |
 ---- ---------- ------- 
  

Существует вторая таблица «T2», в которой хранится ссылка на первичный ключ первой и фактически на саму таблицу, только без слова «table_».

  ------------ -------- -------- -------- -------- 
| rec_number | period | field1 | field2 | field3 |
 ------------ -------- -------- -------- -------- 
| 777        | 092020 | aaa    | bbb    | ccc    |
 ------------ -------- -------- -------- -------- 
| 987        | 102020 | eee    | fff    | ggg    |
 ------------ -------- -------- -------- -------- 
| 123456     | 082020 | xxx    | yyy    | zzz    |
 ------------ -------- -------- -------- -------- 
  

Существует также третья таблица «T3», которая представляет собой соотношение периода и имени таблицы.

  -------- -------------- 
| period | table_name   |
 -------- -------------- 
| 082020 | table_082020 |
 -------- -------------- 
| 092020 | table_092020 |
 -------- -------------- 
| 102020 | table_102020 |
 -------- -------------- 
  

Подскажите, как можно объединить 3 таблицы, чтобы получить динамические данные за несколько периодов. Например: от 15082020 до 04092020, где данные будут расположены в разных таблицах соответственно

Комментарии:

1. Исправьте свой дизайн. Не храните данные в имени таблицы. У вас должна быть одна таблица со столбцом для обозначения значения whatever '082020' , '092020' represent .

2. Зачем вам вообще нужно иметь несколько таблиц? У вас уже есть date столбец в таблице. Поместите все в одну таблицу, и вы можете выбросить T3

3. @DaleK Я попытался реализовать это решение с помощью курсора, выбрав данные и вставив их во временную таблицу. Это работает, но очень медленно

4. @Larnu Потому что за каждый месяц собирается около 5 миллионов записей. и чтобы упростить выбор данных

5. «и чтобы упростить выбор данных» , тогда вы сможете легко выполнить эту операцию, если это так «просто» при использовании этого подхода. 😉 Очевидно, что это не так , как если бы это было «легко», вы бы не задавали этот вопрос. Что проще , так это добавить WHERE YourVarcharColumn = '092020' , не имея 10 таблиц. В противном случае изучите разбиение на разделы. Реальное решение — исправить дизайн.

Ответ №1:

На самом деле нет веской причины для хранения данных в этом формате. Это превращает выполнение запросов в кошмар.

Если вы не можете изменить формат данных, каждый месяц добавляйте представление, объединяющее данные:

 create view t as
    select '202010' as YYYYMM, t.*
    from table_102020
    union all
    select '202008' as YYYYMM, t.*
    from table_092020
    union all
    . . .;
  

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

Что вы должны делать? Ну, 5 миллионов строк в месяц — это на самом деле не так много данных. Но если вас это беспокоит, вы можете использовать разделение таблиц для хранения данных по месяцам. Это может быть немного сложнее; например, первичный ключ должен включать ключ разделения.

Комментарии:

1. Спасибо! Я придумал решение: я создал хранимую процедуру и передаю ей два параметра: период от и до. И я формирую sql-запрос в цикле