Базовод для сасового костыля

Форум для обсуждения деталей разработки программы SAS.Планета

Модераторы: vdemidov, Tolik

Базовод для сасового костыля

Сообщение Parasite » 18 сен 2012, 14:27

Господа, кто в теме - подскажите плиз?

Имеется база данных, в которой - туева хуча одинаковых по структуре таблиц. Различны сами хранимые в таблицах данные.
Как мне сделать так, чтобы одним коротеньким селектом поискать и выбрать данные со всей кучи таблиц, а не перебирать и опрашивать каждую таблицу последовательно? Что-то туплю... :oops:

Код: Выделить всё
DB:
  |-Table0
  |  |-Col0,Col1,Col2...
  |
  |-Table1
  |  |-Col0,Col1,Col2...
  |
  |-Table2
  |  |-Col0,Col1,Col2...
.......

Надо:
SELECT * FROM <тут, собссно, сабж> WHERE <условие>
вместо
SELECT * FROM DB.Table0 WHERE <условие>; SELECT * FROM DB.Table1 WHERE <условие>; SELECT * FROM DB.Table2 WHERE <условие>;

Просто число таблиц стремится к нескольким сотням, и перебирать их уже весьма затратно (хоть и работоспособно). Вроде бы как-то можно было сделать через VIEW говорят, но что-то пока получается всякая хрень.

PS: DB = PostgreSQL
PPS: нужно для костыля к САСу, так что немножко тематическое. :)
The only difference between me and a mad man is that I am not mad. /Salvador Dali/
Изображение
Аватара пользователя
Parasite
Администратор
 
Сообщения: 5614
ICQ: 15819243
Зарегистрирован: 23 окт 2008, 17:38
Благодарил (а): 119 раз.
Поблагодарили: 439 раз.

Re: Базовод для сасового костыля

Сообщение Sigurt » 18 сен 2012, 15:16

Что-то кроме union ничего в голову не приходит, но по сути это не сильно отличается от кучи запросов, что уже имеется...

Либо один раз сделать
Код: Выделить всё
create view public.view1 (col0,col1,col2...) as
SELECT * FROM table1
UNION
SELECT * FROM table2

А потом запросами с представлениями и работать, но фактически не сильное отличие от того что у вас есть =)

За это сообщение автора Sigurt поблагодарил:
Parasite (18 сен 2012, 16:50)
Sigurt
Новичок
 
Сообщения: 14
Зарегистрирован: 06 июн 2012, 13:01
Благодарил (а): 3 раз.
Поблагодарили: 6 раз.

Re: Базовод для сасового костыля

Сообщение Parasite » 18 сен 2012, 16:45

Там еще и дело в том, что запрос со стороны клиента можно делать только один: либо никаких последовательных переборов табличек и брать всё за раз (и до сего момента так оно и было - была всего одна табличка, но со временем она распухла до >200Гб и уже пару раз крэшилась по индексам...хорошо хоть бэкапы были), либо делать промежуточный проксик еще и на пути к базоводу, который и будет перебирать кучу селектов от себя - а выплевывать в запросившего только финальный результат....Второй вариант - корявый и угробищный. :(

Может есть какой-нибудь синтаксис селекта, в котором не надо указывать целевую таблицу (или указать * )? :) Было бы весьма красиво: SELECT * FROM * WHERE <условие> limit X, и дело с концом...

Sigurt писал(а):Что-то кроме union ничего в голову не приходит, но по сути это не сильно отличается от кучи запросов, что уже имеется...

Кстати, а можно и так попробовать, да. Ничего не мешает быть сотне-другой селектов внутри базовода - и пусть их, машинка весьма мощная...Лишь бы для стороны клиента это было прозрачно и приходил общий ответ со всех таблиц в ответ на один запрос....
Попробую, отпишусь. :)
The only difference between me and a mad man is that I am not mad. /Salvador Dali/
Изображение
Аватара пользователя
Parasite
Администратор
 
Сообщения: 5614
ICQ: 15819243
Зарегистрирован: 23 окт 2008, 17:38
Благодарил (а): 119 раз.
Поблагодарили: 439 раз.

Re: Базовод для сасового костыля

Сообщение vasketsov » 19 сен 2012, 20:15

Варианты:
1. UNION ALL.
2. Запускать хранимую процедуру, слить в хранимой процедуре во времянку (создать в процедуре), потом селектить из неё, на выходе времянка сама умрёт - это если СУБД поддерживает селекты наружу из хранимок.
vasketsov
Специалист
 
Сообщения: 901
Зарегистрирован: 25 июл 2009, 21:15
Благодарил (а): 0 раз.
Поблагодарили: 193 раз.

Re: Базовод для сасового костыля

Сообщение Parasite » 22 сен 2012, 18:36

Что-то не выходит каменный цветок.

1.
Код: Выделить всё
SELECT * FROM "Table0" where <условие> UNION SELECT * FROM "Table1" where <условие> UNION SELECT * FROM "Table2" where <условие> UNION SELECT * FROM "Table3" where <условие>;

= работает как задумано, но перечисление таблиц и условий приближает длину строки запроса к бесконечности, как и время отработки.

2. UNION ALL - то же самое что и п.1. То есть, никакой разницы не отмечено.

3.
Код: Выделить всё
SELECT * FROM "Table0","Table1","Table2","Table3"  where "id" is not null;

дает нам еррор:
Код: Выделить всё
ERROR: column reference "id" is ambiguous
SQL state: 42702

Если убрать перечисление всех таблиц, оставив только одну (любую) - то всё работает, но только с нею.

4. Со вьюшками - беда. Киент шлет разные селекты (с разной комбинацией условий и запрашиваемых полей), и на каждую комбинацию надо делать во вьюшке (коль скоро, как я понимаю - они фиксированы на стадии "AS (<запрос>)", и со стороны клиента произвольный запрос через них не отработает)?
The only difference between me and a mad man is that I am not mad. /Salvador Dali/
Изображение
Аватара пользователя
Parasite
Администратор
 
Сообщения: 5614
ICQ: 15819243
Зарегистрирован: 23 окт 2008, 17:38
Благодарил (а): 119 раз.
Поблагодарили: 439 раз.

Re: Базовод для сасового костыля

Сообщение movnet » 23 сен 2012, 20:00

SELECT * FROM "Table0","Table1","Table2","Table3"
where
"Table0.id" is not null
or
"Table1.id" is not null
or
"Table2.id" is not null
or
"Table3.id" is not null;
movnet
Новичок
 
Сообщения: 8
Зарегистрирован: 11 июл 2009, 14:48
Откуда: Украина, Тернополь
Благодарил (а): 2 раз.
Поблагодарили: 0 раз.

Re: Базовод для сасового костыля

Сообщение Parasite » 23 сен 2012, 22:24

movnet писал(а):SELECT * FROM "Table0","Table1","Table2","Table3"
where
"Table0.id" is not null
or
"Table1.id" is not null
or
"Table2.id" is not null
or
"Table3.id" is not null;

Работает, но запрос получается еще более монструозным чем с UNION. Представьте, что таблиц - около 500 штук? Из надо будет все перечислить, причем два раза (во FROM и в OR), и еще 500 раз указать одно и то же условие на каждую...Каждый запрос займет по паре страниц текста, и работать будет точно так же неторопливо и последовательно, а выхлоп как я понимаю будет только с первой попавшейся (коль скоро тут OR а не объединение). В чем, собственно, и вопрос.
The only difference between me and a mad man is that I am not mad. /Salvador Dali/
Изображение
Аватара пользователя
Parasite
Администратор
 
Сообщения: 5614
ICQ: 15819243
Зарегистрирован: 23 окт 2008, 17:38
Благодарил (а): 119 раз.
Поблагодарили: 439 раз.

Re: Базовод для сасового костыля

Сообщение Parasite » 24 сен 2012, 00:02

Нашел изящное решение через наследование.

На стороне базовода (tab, в данном случае - пустая таблица-болванка со структурой, повторенной во всех наших таблицах):
Код: Выделить всё
CREATE TABLE Table1 () INHERITS (tab) ;
....
CREATE TABLE TableХХХ () INHERITS (tab) ;

Добавление новой таблицы, соответственно - одна строчка в базовод разово, ну и заполнение данными.


На стороне клиента вообще ничего менять не надо даже при добавлении новых таблиц:
Код: Выделить всё
SELECT * FROM tab;


А
Код: Выделить всё
SELECT *,tableoid FROM tab;

еще и отдает указатели на все наследованные таблицы.

Всем спасибо, все свободны. 8-)
The only difference between me and a mad man is that I am not mad. /Salvador Dali/
Изображение
Аватара пользователя
Parasite
Администратор
 
Сообщения: 5614
ICQ: 15819243
Зарегистрирован: 23 окт 2008, 17:38
Благодарил (а): 119 раз.
Поблагодарили: 439 раз.


Вернуться в Раздел для разработчиков программы SAS.Планета

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron