Помогите сделать вложеный запрос типа SELECT ... FROM (SELECT ...)

  • Автор темы sidewinder
  • Дата начала

sidewinder

Guest
Помогите сделать вложеный запрос типа SELECT ... FROM (SELECT ...)

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

Сделал я такую конструкцию:
SELECT quest_p FROM (SELECT name_r FROM themes WHERE id=1);

- интерпретатор говорит, что надо использовать что-то типа:
sub-SELECT in FROM must have an alias
For example, FROM (SELECT ...) [AS] foo

Только на понятно, куда этот AS вставить?

Если сделать так:
SELECT * FROM (SELECT name_r FROM themes WHERE id=1) AS th;

то он выводит это самое name_r, а основной запрос не выполняется.

( postgres (PostgreSQL) 7.1.3 )
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Re: Помогите сделать вложеный запрос типа SELECT ... FROM (SELECT ...)

Автор оригинала: sidewinder
Надо найти имя таблицы из другой таблицы, а потом из этой найденной таблицы сделать выборку.
Сделать это стандартными средствами SQL нельзя. Кроме того, раз такая задача вообще возникла, значит со схемой базы проблемы.
 

sidewinder

Guest
Понятно.
Надо по мере работы системы создавать новые таблицы, естественно имена этих таблиц надо где-то хранить. Как такое можно сделать?
Или это считается плохой схемой?
Можно, конечно, сделать одну таблицу вместо того, что бы создаваь новые, но я прикинул, что она может вырасти до таких размеров, что для любого запроса множество записей удовлетворяющих запросу по отношению ко всем записям будет уменьшаться и это приведёт к выполнению избыточных операций. Например: 100 записей нам надо выбрать 5 но 2 критериям. Первому критерию удовлетворяют только 10 записей. Если таблицу со 100 записями разделить на 10 - тоеть из двух критериев 1 выбирает таблицу, ва второй критерий выбирает уже записи в таблице.

А использовать PL/PgSQL можно для этих целей? Можно присвоить переменной имя таблицы?
 

Serguitar

Новичок->продвинутый
я прикинул, что она может вырасти до таких размеров, что для любого запроса множество записей удовлетворяющих запросу по отношению ко всем записям будет уменьшаться и это приведёт к выполнению избыточных операций.
Ты не прикидывай, ты подумай хорошенько. Попробуй иначе построить структуру базы.

Например: 100 записей нам надо выбрать 5 но 2 критериям. Первому критерию удовлетворяют только 10 записей. Если таблицу со 100 записями разделить на 10 - тоеть из двух критериев 1 выбирает таблицу, ва второй критерий выбирает уже записи в таблице
Напиши понятнее и без ошибок, если тебе не трудно, а то "Например" превращается в "догадайтесь сами".
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: sidewinder
Можно, конечно, сделать одну таблицу вместо того, что бы создаваь новые, но я прикинул, что она может вырасти до таких размеров, что для любого запроса множество записей удовлетворяющих запросу по отношению ко всем записям будет уменьшаться и это приведёт к выполнению избыточных операций.
Для борьбы с этой "проблемой" человечество придумало индексы, которые и рекомендую использовать.

Не стоит заниматься твоей "оптимизацией" до того, как ты выяснил что
1) система тормозит
2) система тормозит именно из-за размера таблицы
3) разбиение таблицы на несколько позволяет решить проблему.

А использовать PL/PgSQL можно для этих целей? Можно присвоить переменной имя таблицы?
Можно, но не обязательно нужно.
 

sidewinder

Guest
Спасибо.
Я тут ещё подумал... В общем даже если оставить вопрос с оптимизацией в стороне, остаются ещё временные таблицы. Нужно где-то хранить их имена.
В общем вопрос сводится к следующему:

CREATE FUNCTION ct(param,...) RETURN boolean AS'
DECLARE
tname ALIAS FOR $1;
BEGIN
CREATE TABLE tname (...);
...
END;
' LANGUAGE 'plpgsql';
Какой тип следует использовать вместо param?
И может что-то ещё не правильно в этой конструкции?
Или есть альтернативный вариант? ( что имелл в виду Sad Spirit, когда сказал: "Можно, но не обязательно нужно." в отношении использования plpgsql?)
 

nickg

Guest
Re: Помогите сделать вложеный запрос типа SELECT ... FROM (SELECT ...)

Originally posted by sidewinder
Надо найти имя таблицы из другой таблицы, а потом из этой найденной таблицы сделать выборку.

Сделал я такую конструкцию:
SELECT quest_p FROM (SELECT name_r FROM themes WHERE id=1);

- интерпретатор говорит, что надо использовать что-то типа:
sub-SELECT in FROM must have an alias
For example, FROM (SELECT ...) [AS] foo

Только на понятно, куда этот AS вставить?

Если сделать так:
SELECT * FROM (SELECT name_r FROM themes WHERE id=1) AS th;

то он выводит это самое name_r, а основной запрос не выполняется.

( postgres (PostgreSQL) 7.1.3 )
Вложенный запрос должен иметь алиас -- это обязательно. И Алиас ты проставил верно (as th). А name_h он выводит потому, что только name_h и выбирается во вложенном запросе. Просто подумай, как это работает: вложенный запрос отбирает name_h, создавая своего рода таблицу из одного столбца name_h, потом из этой "таблицы" ты отбираешь все столбцы (SELECT *). И откуда там возьмутся другие столбцы, кроме name_h?
 

Postgres

Guest
Вот рабочий пример (испоьзуется на www.biz.ua):

SELECT n1.group_id
FROM
(SELECT grp.group_id, Count(grp.id_handle) AS Count_handle
FROM nic_handle INNER JOIN grp ON nic_handle.id_handle = grp.id_handle
WHERE nic_handle.nic_hande IN ('biz','host')
GROUP BY grp.group_id) AS n1
INNER JOIN
(SELECT grp.group_id, Count(grp.group_id) AS Count_group
FROM (SELECT grp.group_id, Count(grp.id_handle) AS Count_handle
FROM nic_handle INNER JOIN grp ON nic_handle.id_handle = grp.id_handle
WHERE nic_handle.nic_hande IN ('biz','host')
GROUP BY grp.group_id) AS n1 INNER JOIN grp ON n1.group_id = grp.group_id
GROUP BY grp.group_id) AS n2
ON (n1.Count_handle = n2.Count_group) AND (n1.group_id = n2.group_id)
WHERE ((n1.Count_handle=2));

Но его бы оптимизировать .... а я еще не раобрался как :(
смысл в том, что здесь есть 2 одинаковых вложенных запроса (AS n1)..
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: sidewinder

Какой тип следует использовать вместо param?
И может что-то ещё не правильно в этой конструкции?
Или есть альтернативный вариант? ( что имелл в виду Sad Spirit, когда сказал: "Можно, но не обязательно нужно." в отношении использования plpgsql?)
пардон, что-то пропустил развитие этой темы.

я уже говорил, что всё создание таблиц и прочей лабуды должно делаться через EXECUTE (не тот, который с PREPARE).

Код:
CREATE OR REPLACE FUNCTION test_create(text)
RETURNS void
AS '
DECLARE
    tmpname ALIAS FOR $1;
BEGIN
    EXECUTE ''CREATE TABLE '' || quote_ident(tmpname) || '' (field text)'';
    RETURN null;
END;
' LANGUAGE plpgsql;
запрос-то динамический на самом деле.
 

anec

Guest
Ну вы что? Временные таблицы, запросы...
Что за чушь?
Во-первых, Постгрес пректасно поддерживает встроенные запросы
Во-вторых, если тебе из одной таблицы нужно вытащить подтаблицу и потом из нее сделать выборку, то это проблема оганизации таблиц. С такой организацией и при больших размерах, даже с индексацией система будет жутко тормозить. Автору этой темы советую просто почитать про нормальные формы (НФ).
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: anec
Ну вы что? Временные таблицы, запросы...
Что за чушь?
Во-первых, Постгрес пректасно поддерживает встроенные запросы
Пришло начальство и всех построило.

Не соблаговолит ли начальство прочитать исходный вопрос, и осознать, что несмотря на тему, к вложенным запросам он отношение имеет весьма косвенное?..
 
Сверху