Форум: "Начинающим";
Текущий архив: 2006.12.17;
Скачать: [xml.tar.bz2];
ВнизПовторное использование результата SQL-запроса Найти похожие ветки
← →
Kostafey © (2006-11-28 22:43) [0]Уважаемые мастера ! Прошу оказать содействие в очередном ламеском вопросе.
Посылаю запросы в SQL Server 20005.
И вот о чем начинаю задумываться.
Запрос формируется на основе нескольких вложенных коррелированных запросов.
Фрагмент подзапроса участвует в очередном подзапросе. Например:
select r.РТП,
(select count(a.N_ZVK)
from ZVK1 a, zvkrtp z
where (a.N_ZVK = z.nzvk) and
(z.rtp=r.Код) and
(a.DATE_ZVK1 between @DateFrom and @DateTo)) as Kol1,
round((select count(a.N_ZVK)
from ZVK1 a, zvkrtp z
where (a.N_ZVK = z.nzvk) and
(z.rtp=r.Код) and
(a.DATE_ZVK1 between @DateFrom and @DateTo))*100.0/500,2) as Acount1,
(select count(a.N_ZVK)
from ZVK1 a, zvkrtp z
where (a.N_ZVK = z.nzvk) and
(z.rtp=r.Код) and
(a.DATE_ZVK1 between @DateFrom_s and @DateTo_s)) as Kol2,
round((select count(a.N_ZVK)
from ZVK1 a, zvkrtp z
where (a.N_ZVK = z.nzvk) and
(z.rtp=r.Код) and
(a.DATE_ZVK1 between @DateFrom_s and @DateTo_s))*100.0/500,2) as Acount2,
(select count(a.N_ZVK)
from ZVK1 a, zvkrtp z
where (a.N_ZVK = z.nzvk) and
(z.rtp=r.Код) and
(a.DATE_ZVK1 between @DateFrom and @DateTo))-
(select count(a.N_ZVK)
from ZVK1 a, zvkrtp z
where (a.N_ZVK = z.nzvk) and
(z.rtp=r.Код) and
(a.DATE_ZVK1 between @DateFrom_s and @DateTo_s)) as Delfakt,
from RTP r
Хорошо бы в место этого писать что-то вроде:
select r.РТП,
(select count(a.N_ZVK)
from ZVK1 a, zvkrtp z
where (a.N_ZVK = z.nzvk) and
(z.rtp=r.Код) and
(a.DATE_ZVK1 between @DateFrom and @DateTo)) as Kol1,
round((Kol1)*100.0/500,2) as Acount1,
(select count(a.N_ZVK)
from ZVK1 a, zvkrtp z
where (a.N_ZVK = z.nzvk) and
(z.rtp=r.Код) and
(a.DATE_ZVK1 between @DateFrom_s and @DateTo_s)) as Kol2,
round((Kol2)*100.0/500,2) as Acount2,
(Kol1)-(Kol2) as Delfakt,
from RTP r
← →
Palladin © (2006-11-28 23:02) [1]смотри в сторону User Defined Functions
← →
Kostafey © (2006-11-28 23:15) [2]> [1] Palladin © (28.11.06 23:02)
> смотри в сторону User Defined Functions
Спасибо, приму к сведению.
Да, к сожалению у меня довольно убогие знания по SQL.
Сложности по тому чтобы вбить любое количество кода нет.
Вопрос скорее в эффективности и, даже более всего, в красоте кода...
Не подскажете хорошие книги/статьи по тематике (кроме Google) ?
← →
Palladin © (2006-11-28 23:38) [3]www.sql.ru
Book online
← →
Kostafey © (2006-11-29 03:07) [4]Если я не ошибаюсь, то > User Defined Functions пререгатива TSQL?
А то что-то я не могу найти в литературе по SQL про них ничего. :(
← →
ЮЮ © (2006-11-29 04:34) [5]А я бы посоветовал смотреть в сторону оптимизации.
Твой запрос - это 6 практически одинаковах подзапроса, пыполняемых для каждой записи из RTP. т.е. вложенный пгрегатный запрос выполняется 6 * RTP.RecordCount раз.
А при правильном написнии запроса хватило бы по одному разу для пар @DateFrom,@DateTo и @DateFrom_s, @DateTo_s:select
РТП,
s.Cnt as Kol1,
case when s.Cnt is null then null else round(s.Cnt/5, 2) end as Acount1,
s_s.Cnt as Kol2,
case when s_s.Cnt is null then null else round(s_s.Cnt/5, 2) end as Acount2,
isnull(s.Cnt, 0) - isnull(s_s.Cnt, 0) as Delfakt
from
RTP r
LEFT JOIN (
// этот подзапрос даст count(a.N_ZVK) для каждого значения z.rtp
select z.rtp, count(a.N_ZVK) cnt
from
ZVK1 a,
JOIN zvkrtp ON (a.N_ZVK = z.nzvk) and
where
(a.DATE_ZVK1 between @DateFrom and @DateTo))
group by
z.rtp
) s ON r.Код = s.rtp
LEFT JOIN (
// этот подзапрос даст count(a.N_ZVK) для каждого значения z.rtp
select z.rtp, count(a.N_ZVK) cnt
from
ZVK1 a,
JOIN zvkrtp ON (a.N_ZVK = z.nzvk) and
where
(a.DATE_ZVK1 between @DateFrom_s and @DateTo_s))
group by
z.rtp
) s_s ON r.Код = s_s.rtp
← →
Kostafey © (2006-11-29 09:45) [6]> [5] ЮЮ © (29.11.06 04:34)
пишет:
Incorrect syntax near the keyword "JOIN".
Что нужно исправить ?
← →
Anatoly Podgoretsky © (2006-11-29 10:10) [7]> Kostafey (29.11.2006 09:45:06) [6]
> Что нужно исправить
Запрос
← →
Kostafey © (2006-11-29 11:09) [8]> [7] Anatoly Podgoretsky © (29.11.06 10:10)
> > Kostafey (29.11.2006 09:45:06) [6]
> > Что нужно исправить
> Запрос
Сейчас упаду со смеху.
Хорошо, не нужно приводить пример насилования моего SQL-запроса (хотя пример в [0] рабочий).
Я думаю, что > [5] ЮЮ © (29.11.06 04:34) в основном прав, но его я понимаю с трудом
(кроме того в нем есть ошибки синтаксита > [6] Kostafey © (29.11.06 09:45)).
Просто приведите пожалуйста стурктуру того запроса, кторый должен быть.
← →
ЮЮ © (2006-11-29 12:36) [9]Просто приведите пожалуйста стурктуру того запроса, кторый должен быть.
from
RTP r
LEFT JOIN ( <подзапрос> ) s ON r.Код = s.rtp
LEFT JOIN ( <подзапрос> ) s_s ON r.Код = s_s.rtp
(кроме того в нем есть ошибки синтаксита >
дельфийские комменарии
// этот подзапрос даст count(a.N_ZVK) для каждого значения z.rtp
замени на SQL-кие
-- этот подзапрос даст count(a.N_ZVK) для каждого значения z.rtp
/* этот подзапрос даст count(a.N_ZVK) для каждого значения z.rtp */
← →
Kostafey © (2006-11-29 18:43) [10]> [9] ЮЮ © (29.11.06 12:36)
> (кроме того в нем есть ошибки синтаксита >
> дельфийские комменарии
> // этот подзапрос даст count(a.N_ZVK) для каждого значения
> z.rtp
> замени на SQL-кие
> -- этот подзапрос даст count(a.N_ZVK) для каждого значения
> z.rtp
> /* этот подзапрос даст count(a.N_ZVK) для каждого значения
> z.rtp */
Да, но я это, конечно, знаю.
Ошибка вовсе не в комментарии.
← →
Kostafey © (2006-11-29 23:27) [11]> [5] ЮЮ © (29.11.06 04:34)
О! Понял что надо исправить !
Запрос прекрасно работает:
select
РТП,
case when s.Cnt is null then 0 else s.Cnt end as Kol1,
case when s.Cnt is null then 0 else round(s.Cnt/5, 2) end as Acount1,
case when s_s.Cnt is null then 0 else s_s.Cnt end as Kol2,
case when s_s.Cnt is null then 0 else round(s_s.Cnt/5, 2) end as Acount2,
isnull(s.Cnt, 0) - isnull(s_s.Cnt, 0) as Delfakt,
1 as Dummy
from
RTP r
LEFT JOIN (
-- этот подзапрос даст count(a.N_ZVK) для каждого значения z.rtp
select z.rtp, count(a.N_ZVK) cnt
from
ZVK1 a
JOIN zvkrtp z ON (a.N_ZVK = z.nzvk)
where
(a.DATE_ZVK1 between @DateFrom and @DateTo)
group by
z.rtp
) s ON r.Код = s.rtp
LEFT JOIN (
-- этот подзапрос даст count(a.N_ZVK) для каждого значения z.rtp
select z.rtp, count(a.N_ZVK) cnt
from
ZVK1 a
JOIN zvkrtp z ON (a.N_ZVK = z.nzvk)
where
(a.DATE_ZVK1 between @DateFrom_s and @DateTo_s)
group by
z.rtp
) s_s ON r.Код = s_s.rtp
Были пара синтаксических ошибок, но я вообще не представляю как можно ТАКОЕ написать не имея возможности просмотреть результат !
Спасибо огромное! Гораздо более красивый и изящный код !
Правда я с таким SQL я не владею и все что идет ниже from RTP r... я не понимаю.
Скажите речь идет о внешних соединениях так?
← →
ЮЮ © (2006-11-30 03:20) [12]
> Скажите речь идет о внешних соединениях так?
Речь идет о соединения вообще, не важно вутренниие они или внешние. Кстати, INNER и OUTER я никогда не пишу, поэтому для себя рассматриваю только левое (LEFT) и обычное соединение.
При выборе из двух и более табли всегд есть соединение, только неявное.SELECT FROM a, b WHERE a.b = b.a
эквивалентноSELECT FROM a JOIN b ON a.b = b.a
Во-первых, когда таблиц в запросе десяток достаточно пропустить одно из услвий связи в WHERE части и вместо связанных таблиц получим их произведение.
Во вторых ON гораздо шире по возможностям, чем WHERE:SELECT FROM
a
LEFT JOIN b ON
(a.b = b.a) AND (a.type = :Type) AND (b.[Date] BETWEEN :D1 AND :D2 )
т.е. можно связывать не все записи из a, в на записи в b наложить ограничения.
более того, можно для разных записей использовать разные ограничения:
Во вторых ON гораздо шире по возможностям, чем WHERE:SELECT FROM
a
JOIN b ON
(a.b = b.a) AND (
(a.type = :Type) AND (b.[Date] BETWEEN :D1 AND :D2 )
OR
(a.type <> :Type) AND (b.[Date] <:D1)
соединив же их просто а, b получить такой результат сразу, без case в списке выбираемых полей. Но это хорошо на MS SQL, где case есть, а такое работает и в Local SQL.
LEFT JOIN и просто JOIN отличаются же тем, что LEFT JOIN ставим тогда, когда нас интересуют все записи из a, независимо от того, есть ли соответствующие записи в b.
Т.е. если в твоем примере не нужны был записи, если count по любому из агрегирующих подзапросов = 0, то вместо LEFT JOIN можно было бы использовать JOIN.
Ну и, наконец, MS SQL позволяет вместо таблиц использовать в запросах именнованные подзапросы, т.е. не простоa
, а (<подзапрос>) a
З.Ы. Ну что ещё остальсь непонятки по части того , что идет ниже from RTP r? :)
← →
ЮЮ © (2006-11-30 03:26) [13]Во-первых, ...
Во вторых, ...
Наконец, при такой записи условие связи и пропустить труднее и сами связи становятся нагляднее, так как прописаны отдельно для каждой присоединяемой таблицы, а не савлены в огромную кучу в общем для всех WHERE
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.12.17;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.041 c