Форум: "Базы";
Текущий архив: 2005.03.13;
Скачать: [xml.tar.bz2];
ВнизSQL Запрос Найти похожие ветки
← →
REA (2005-02-10 11:26) [0]Добрый день. Помогите плз составить 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" то тоже пойдет
← →
Александр Иванов © (2005-02-10 11:37) [1]Вот так попробуй:
select T2.N, T2.Time, T2.X1 from T2
where Time = (select max(tt.Time) from T2 as tt where T2.N = tt.N)
← →
Sergey13 © (2005-02-10 11:44) [2]Или вот так
select T1.N, T2.Time, T2.X1
from T1,T2
where T1.N=T2.N and
T2.Time = (select max(tt.Time) from T2 as tt where TT.N = T1.N)
← →
Александр Иванов © (2005-02-10 11:47) [3]Sergey13 © (10.02.05 11:44) [2]
А зачем использовать 1-ю таблицу вообще? :)
← →
REA (2005-02-10 11:51) [4]Че то не получается. Запрос не выполняется, а если пошаманить, то возвращает одну запись. Переписал [1] для реальных таблиц в таком виде (не работает):
select tankslog.tankno, tankslog.logtime from tankslog
where logtime = (select max(tt.logtime) from tankslog as tt where tankslog.tankno = tt.tankno)
← →
Johnmen © (2005-02-10 11:53) [5]>REA (10.02.05 11:51) [4]
Везде используй псевдонимы таблиц !
← →
Sergey13 © (2005-02-10 11:54) [6]2[3] Александр Иванов © (10.02.05 11:47)
Чтобы не выводилось несколько одинаковых из второй. Может я и ошибаюсь.
← →
REA (2005-02-10 11:57) [7]В виде из 2 работает, но настораживает что есть два сравнения T1.N=T2.N
И первая таблица пожалуй тоже нужна - допустим там есть еще поле T1X, которое надо возвратить в запросе.
← →
REA (2005-02-10 11:58) [8]>Везде используй псевдонимы таблиц
А зачем, если не секрет?
← →
Sergey13 © (2005-02-10 12:02) [9]2[7] REA (10.02.05 11:57)
>В виде из 2 работает, но настораживает что есть два сравнения T1.N=T2.N
Где? Есть T1.N=T2.N и T1.N=TT.N -это разные вещи. TT<>T2.
← →
ЮЮ © (2005-02-10 12:03) [10]С помощью одного SQL-запроса можно получить только
1 14:00
2 15:00
Для получения требуемого надо соединить это результ с таблицей.
Т.к. в IB нет механизма подзапросов, то, ИМХО, - одним запросом - нельзя
← →
Johnmen © (2005-02-10 12:03) [11]>А зачем, если не секрет?
Чтобы однозначно определять, из какой таблицы указываемое поле.
← →
REA (2005-02-10 12:07) [12]В таком виде (без T1.N=T2.N) тоже работает:
... where Tankslog.logTime = (select max(Tankslog.logTime) from Tankslog where Tankslog.tankno = Tanks.tankno)
>Чтобы однозначно определять, из какой таблицы указываемое поле.
А если писать в виде таблица.поле? Если таблица не указана, значит такое поле только в одно таблице.
И еще: что лучше использовать SELECT FROM SELECT MAX() или JOIN?
← →
Johnmen © (2005-02-10 12:16) [13]>А если писать в виде таблица.поле?
Если не хочешь неоднозначностей (которые ты понимаешь так, а парсер по-другому), всегда алиастаблицы.поле
← →
REA (2005-02-10 12:22) [14]И в таком виде как ни странно работает:
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)
Так как лучше то?
← →
Sergey13 © (2005-02-10 12:29) [15]2[14] REA (10.02.05 12:22)
>И в таком виде как ни странно работает:
Осталось выяснить правильно ли. 8-)
← →
Johnmen © (2005-02-10 12:30) [16]>ЮЮ © (10.02.05 12:03) [10]
>Т.к. в IB нет механизма подзапросов,
Хм... Что имеется в виду ?
>REA (10.02.05 12:22) [14]
Этот запрос в корне неверен.
Верный - в [1].
← →
REA (2005-02-10 12:58) [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 записей
← →
Anatoly Podgoretsky © (2005-02-10 13:38) [18]Johnmen © (10.02.05 12:03) [11]
Правильнее сказать префиксы, а псевдоними или явные названия таблиц без разницы, если конечно имена таблиц простые, английскии и нет вложенных запросов из самого себя.
← →
Johnmen © (2005-02-10 13:39) [19]Ты думаешь, что про алиасы я просто воздух сотрясал ? (в смысле, в форуме флудил :))
select * from tankslog T1
where T1.logtime = (select max(T2.logTime)
from Tankslog T2
where (T2.tankno = T1.tankno)))
← →
Johnmen © (2005-02-10 13:41) [20]>Anatoly Podgoretsky © (10.02.05 13:38) [18]
Ну, само-собой...:)
← →
Anatoly Podgoretsky © (2005-02-10 13:42) [21]Вот, вот как раз тот случай когда нужны псевдонимы, без них задача не решаема.
← →
REA (2005-02-10 14:03) [22]Спасибо. Про алиасы верю и уже переделал с алиасами.
На основе этого запроса получилось:
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?
← →
Johnmen © (2005-02-10 14:28) [23]Ну боже ты мой.........
Уже всё сказали про запрос в [1] и [19].
И даже его написали... Так нет же, придумаем свой бред...:)
Учитесь анализировать и понимать, что вам говорят !
← →
REA (2005-02-10 17:04) [24]В [1] не работает, как я уже говорил. [19] отлично работает, но мне нужно дополнительное условие (wellid = 1 в обоих таблицах) и нужно несколько полей из таблицы 1 (см. [7]). Согласен, что у меня от недостатка опыта получается бред.
>Учитесь анализировать и понимать, что вам говорят !
Пока ничего особо не говорят, а только приводят примеры, которые не всегда работают. Спасибо за содействие и понимание.
← →
ЮЮ © (2005-02-11 03:41) [25]>>ЮЮ © (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 млм в качестве поля возвращаемого НД, ИМНО, не есть хороший стиль. Лучше уж на клиенте (или в ХП) провежаться один раз по двум курсорам и получить необходимые данные, чем для каждой записи выполнять отдельный подзапрос
← →
Johnmen © (2005-02-11 09:41) [26]>ЮЮ © (11.02.05 03:41) [25]
То, что ты написал, не есть "механизм подзапросов". Это просто соединение запроса с таблицей.
А то, что хочет автор, уже написали ранее...
И для каждой записи делать подзапрос ненапряжно, если есть соотв.индексы, и быстрее, чем на клиенте разбирать, и не факт, что медленнее, чем процедура, где наверняка будет запрос с агрегированием и группировкой. А группировка достаточно небыстрый процесс...
← →
REA (2005-02-11 10:35) [27]Автор хочет, чтобы было быстрее: можно select, join или если быстро не получится, то пробежаться по запросу. Пока сделал select (который на самом деле тоже план JOIN) [22] - вроде работает. С join пробовал тоже, но не хватает моих познаний - вариант как в [25] мне самому пожалуй не соорудить.
Спасибо за помощь.
← →
Johnmen © (2005-02-11 10:40) [28]>REA
Ты просто скажи, что есть (структура таблиц с примером наполнения) и что надо (пример выходных данных).
← →
ЮЮ © (2005-02-11 11:01) [29]>если быстро не получится, то пробежаться по запросу
SELECT
tanks.tankno, tankslogg.logtime, tankslogg.<прочие поля>
FROM
tanks
LEFT JOIN tankslog
ON (tanks.tankno = logGrouped.tankno)
ORDER BY 1, 2 DESC
Осталось пробежаться по запросу и делать Suspend в случае смены первого поля и бежать дальше в противном случае.
← →
REA (2005-02-11 13:34) [30]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 13:38) [31]Suspend - это их области хранимых процедур, т.е. вернет с сервера запись клиенту
logGrouped - это возможно только на SQL - использовать запрос как таблицу в операциях связи (logGrouped - алиас подзапроса)
← →
Johnmen © (2005-02-11 14:45) [32]Примерно так, хотя непонятно, что есть 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
Вспомнил, как писал для "Транснефти". Учет резервуаров(танков) хранения нефти, их параметры, обслуживание и дефектоскопия...:)
← →
REA (2005-02-11 17:27) [33]Thanx. WELLID просто часть ключа (номер скважины). После включения WELLID (а без него PLAN NATURAL) получилось IR 2280 и 6, а виде [22] на тех же данных 380 + 30.
Suspend в IB есть? Пока обходился без хранимых процедур.
PS: Это как раз и есть резервуары, но для бурового раствора.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2005.03.13;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.029 c