Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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.039 c
14-1108899022
07BB:080Dh
2005-02-20 14:30
2005.03.13
Кто нибудь на работе слушает "Красную плесень"?


4-1106865030
Atrion
2005-01-28 01:30
2005.03.13
Как создать подкласс WC_LISTVIEW("SysListView32") ?


1-1109695572
Shnabs
2005-03-01 19:46
2005.03.13
Курсор


1-1109267654
aglar
2005-02-24 20:54
2005.03.13
Как сохранить динамически созданные пункты меню?


14-1108709845
WondeRu
2005-02-18 09:57
2005.03.13
Книжная ветка 3: Зарубежная Литература





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский