![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
SQL Запрос [IB6.x]
REA © (2005-02-10 11:26:00)Добрый день. Помогите плз составить SQL запросик:
Есть таблица T1 с полем N:
N
1
2
3
и таблица T2 c полями N, Time, X1
N Time X1
1 13:00 aaa
1 14:00 bbb
2 12:00 ccc
2 15:00 ddd
Нужно получить максимальное время для каждого N:
1 14:00 bbb
2 15:00 ddd
Если будет и "3, NULL, NULL" то тоже пойдет
REA (2005-02-11 17:27:00) [1]Thanx. WELLID просто часть ключа (номер скважины). После включения WELLID (а без него PLAN NATURAL) получилось IR 2280 и 6, а виде [22] на тех же данных 380 + 30.
Suspend в IB есть? Пока обходился без хранимых процедур.
PS: Это как раз и есть резервуары, но для бурового раствора.
Johnmen (2005-02-11 14:45:00) [2]Примерно так, хотя непонятно, что есть WELLID и каким оно боком:
SELECT T1.TANKNO,
T1.TANKGEOMETRY,
T2.TANKACTIVE
FROM Tanks T1, TanksLog T2
WHERE (T1.TANKNO=T2.TANKNO) AND(T2.WELLID=1) AND
(T2.LOGTIME=(SELECT MAX(T3.LOGTIME)
FROM TanksLog T3
WHERE (T3.TANKNO=T2.TANKNO) {возможно AND T3.WELLID=1}))
PS
Вспомнил, как писал для "Транснефти". Учет резервуаров(танков) хранения нефти, их параметры, обслуживание и дефектоскопия...:)
ЮЮ (2005-02-11 13:38:00) [3]Suspend - это их области хранимых процедур, т.е. вернет с сервера запись клиенту
logGrouped - это возможно только на SQL - использовать запрос как таблицу в операциях связи (logGrouped - алиас подзапроса)
REA (2005-02-11 13:34:00) [4]2Johnmen:
Переформулирую задачу:
Есть таблица Tanks c полями +WELLID, +TANKNO, GEOMETRY и таблица TanksLog с полями +WELLID, +TANKNO, +LOGTIME, TANKACTIVE
нужно получить выборку с полями
TANKNO, TANKGEOMETRY, TANKACTIVE для WELLID=1, и всеми (уникальными)TanksLog.TANKNO с максимальным временем LOGTIME для каждого из TANKNO:
WELLID, TANKNO, TANKGEOMETRY
1, 1, 1 ->
1, 2, 2 ->
2, 1, 2
WELLID, LOGTIME, TANKNO, TANKACTIVE
1, 13:00, 1, 1
1, 14:00, 1, 0 ->
1, 14:00, 2, 1
1, 15:00, 2, 1 ->
TANKNO, TANKGEOMETRY, TANKACTIVE
1 1 0
2 2 1
2ЮЮ:
Если честно, пока не понял что есть logGrouped и Suspend, но учту. Спасибо. Сделать две выборки и пробежаться программно я в состоянии сам, но не уверен, что это будет эффективнее, чем запрос.
ЮЮ (2005-02-11 11:01:00) [5]>если быстро не получится, то пробежаться по запросу
SELECT
tanks.tankno, tankslogg.logtime, tankslogg.<прочие поля>
FROM
tanks
LEFT JOIN tankslog
ON (tanks.tankno = logGrouped.tankno)
ORDER BY 1, 2 DESC
Осталось пробежаться по запросу и делать Suspend в случае смены первого поля и бежать дальше в противном случае.
Johnmen (2005-02-11 10:40:00) [6]>REA
Ты просто скажи, что есть (структура таблиц с примером наполнения) и что надо (пример выходных данных).
REA (2005-02-11 10:35:00) [7]Автор хочет, чтобы было быстрее: можно select, join или если быстро не получится, то пробежаться по запросу. Пока сделал select (который на самом деле тоже план JOIN) [22] - вроде работает. С join пробовал тоже, но не хватает моих познаний - вариант как в [25] мне самому пожалуй не соорудить.
Спасибо за помощь.
Johnmen (2005-02-11 09:41:00) [8]>ЮЮ © (11.02.05 03:41) [25]
То, что ты написал, не есть "механизм подзапросов". Это просто соединение запроса с таблицей.
А то, что хочет автор, уже написали ранее...
И для каждой записи делать подзапрос ненапряжно, если есть соотв.индексы, и быстрее, чем на клиенте разбирать, и не факт, что медленнее, чем процедура, где наверняка будет запрос с агрегированием и группировкой. А группировка достаточно небыстрый процесс...
ЮЮ (2005-02-11 03:41:00) [9]>>ЮЮ © (10.02.05 12:03) [10]
>>Т.к. в IB нет механизма подзапросов,
>Johnmen © (10.02.05 12:30) [16]
>Хм... Что имеется в виду ?
Имеется в ввмду, что надо сделать соединение первой таблицы, результата агрегирующего запроса по второй и, наконец, самой второй таблицы. В MS SQL это выгдядедо бы так:
SELECT tanks.tankno, tankslogg.*
FROM
tanks
LEFT JOIN (
SELECT tankno, MAX(logtime) maxlogtime
FROM tankslog
GROUP BY tankno
) logGrouped ON (tanks.tankno = logGrouped.tankno)
LEFT JOIN tankslog ON
(logGrouped.tankno = tankslog.tankno) AND
(logGrouped.maxlogtime= tankslog.logtime)
А использовать SELECT в WHERE млм в качестве поля возвращаемого НД, ИМНО, не есть хороший стиль. Лучше уж на клиенте (или в ХП) провежаться один раз по двум курсорам и получить необходимые данные, чем для каждой записи выполнять отдельный подзапрос
REA (2005-02-10 17:04:00) [10]В [1] не работает, как я уже говорил. [19] отлично работает, но мне нужно дополнительное условие (wellid = 1 в обоих таблицах) и нужно несколько полей из таблицы 1 (см. [7]). Согласен, что у меня от недостатка опыта получается бред.
>Учитесь анализировать и понимать, что вам говорят !
Пока ничего особо не говорят, а только приводят примеры, которые не всегда работают. Спасибо за содействие и понимание.
Johnmen (2005-02-10 14:28:00) [11]Ну боже ты мой.........
Уже всё сказали про запрос в [1] и [19].
И даже его написали... Так нет же, придумаем свой бред...:)
Учитесь анализировать и понимать, что вам говорят !
REA (2005-02-10 14:03:00) [12]Спасибо. Про алиасы верю и уже переделал с алиасами.
На основе этого запроса получилось:
select T1.logtime, T1.tankactive, tt.tankgeometry from tankslog T1, tanks tt where (T1.wellid = 1) And (Tt.wellid = 1) And (tt.tankno = T1.tankno) And (T1.logtime = (select max(T2.logTime)
from Tankslog T2 where (T2.wellid = 1) And (T2.tankno = T1.tankno)))
Indexed Reads: 4 и 30. Это лучше чем 2 и 60?
Anatoly Podgoretsky (2005-02-10 13:42:00) [13]Вот, вот как раз тот случай когда нужны псевдонимы, без них задача не решаема.
Johnmen (2005-02-10 13:41:00) [14]>Anatoly Podgoretsky © (10.02.05 13:38) [18]
Ну, само-собой...:)
Johnmen (2005-02-10 13:39:00) [15]Ты думаешь, что про алиасы я просто воздух сотрясал ? (в смысле, в форуме флудил :))
select * from tankslog T1
where T1.logtime = (select max(T2.logTime)
from Tankslog T2
where (T2.tankno = T1.tankno)))
Anatoly Podgoretsky (2005-02-10 13:38:00) [16]Johnmen © (10.02.05 12:03) [11]
Правильнее сказать префиксы, а псевдоними или явные названия таблиц без разницы, если конечно имена таблиц простые, английскии и нет вложенных запросов из самого себя.
REA (2005-02-10 12:58:00) [17]В таком виде (по мотивам 1) возвращает не то:
select tankno, logtime, tankactive from tankslog where
(logtime = (select max(tt.logTime) from Tankslog tt where (tt.tankno = tankslog.tankno)))
работает по мотивам 2 (wellid - часть primary ключа в обоих таблицах):
select tanks.tankno, tankslog.logtime
from tanks, tankslog
where (tanks.wellid=1) And (tankslog.wellid=1) And (tanks.tankno=tankslog.tankno) and
tankslog.logtime = (select max(tt.logtime) from tankslog tt where tt.wellid = 1 and TT.tankno = tanks.tankno)
но имхо многовато Indexed Reads: 2 и 60 на таблицах из 2 и 5 записей
Johnmen (2005-02-10 12:30:00) [18]>ЮЮ © (10.02.05 12:03) [10]
>Т.к. в IB нет механизма подзапросов,
Хм... Что имеется в виду ?
>REA (10.02.05 12:22) [14]
Этот запрос в корне неверен.
Верный - в [1].
Sergey13 (2005-02-10 12:29:00) [19]2[14] REA (10.02.05 12:22)
>И в таком виде как ни странно работает:
Осталось выяснить правильно ли. 8-)
REA (2005-02-10 12:22:00) [20]И в таком виде как ни странно работает:
select tanks.tankno, tanks.tankgeometry, logtime, tankslog.tankactive from tanks, tankslog where
logtime = (select max(logTime) from Tankslog)
Планы:
PLAN (TANKSLOG NATURAL)
PLAN JOIN (TANKS NATURAL,TANKSLOG NATURAL)
Так как лучше то?