Xpoint
   [напомнить пароль]

Нужна помощь с запросом

Метки: [без меток]
2006-03-29 05:19:39 [обр] Роман Чемисов(0/350)[досье]

Дурацкое название темы, но ничего лучше придумать не смог :-)
Ситуация такая: Firebird 1.5. Табличка

CREATE TABLE T_FIRM (
    INSUSER     VARCHAR(20) DEFAULT '' NOT NULL COLLATE PXW_CYRL,
    NAME        VARCHAR(250) DEFAULT '' NOT NULL COLLATE PXW_CYRL,
    "_VERSION"  IDENTIFIER /* IDENTIFIER = INTEGER NOT NULL */,
    INSDATE     TIMESTAMP,
    UPDUSER     VARCHAR(20) DEFAULT '' NOT NULL COLLATE PXW_CYRL,
    UPDDATE     TIMESTAMP,
    "_UPDTIME"  UPDTIMER /* UPDTIMER = TIMESTAMP NOT NULL */,
    ADMAT       IDENT_REF_NULL /* IDENT_REF_NULL = INTEGER DEFAULT NULL */
);
ALTER TABLE T_TESTFIRM ADD CONSTRAINT PK_T_TESTFIRM PRIMARY KEY ("_VERSION");
ALTER TABLE T_TESTFIRM ADD CONSTRAINT FK_T_TESTFIRM_ADMAT FOREIGN KEY (ADMAT) REFERENCES T_DESTFADM ("_ID");

INSUSER — пользователь, создавший запись;
NAME — имя записи (название фирмы);
INSDATE — время создания записи;
UPDUSER — пользователь, обновивший запись (для новой записи это '');
UPDDATE — время обновления записи (для новой записи это NULL);
_UPDTIME — время обновления/создания (для новой записи это время создания, а для обновлённой это время обновления);
ADMAT — это ссылка на код фирмы из другой таблицы (код не меняется).

Выглядит это примерно так:

STV|Джэт Трэвал,ООО|33|10.03.2006 13:00||null|10.03.2006 13:00|37
STV|Джэт Трэвал,ООО|1092|10.03.2006 13:00|STV|24.03.2006 16:47|24.03.2006 16:47|37
STV|Джэт Трэвал, ООО|1096|10.03.2006 13:00|STV|24.03.2006 16:52|24.03.2006 16:52|37

Мне надо выбрать для каждой фирмы последнюю запись (в приведённом выше варианте это третья строчка). Т. е. если были изменения, то выбрать нужно последний вариант изменений. А если изменения не вносились, то просто берём запись.
Вариант

SELECT INSUSER, NAME, ADMAT
FROM T_FIRM;

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

спустя 3 часа 23 минуты [обр] Vladmir[досье]

Если я правильно понял, то последнее обновление или время создания находится в
_UPDTIME.

Тогда у меня получается через вложенный запрос:

select name, admat, _UPDTIME from t_firm t1 
where _UPDTIME = 
(select  max(_UPDTIME) from t_firm t2 where t1.name = t2.name)

Не работал с Firebird, но синтаксис вроде стандартный

спустя 21 минуту [обр] Роман Чемисов(0/350)[досье]
Vladmir[досье]
Спасибо. Всё работает. Как-то я не подумал о вложенном запросе.
спустя 3 минуты [обр] Денис Гетман(5/228)[досье]
 А в Firebird разве нет оператора HAVING? Вроде в сочетании с max он и должен давать нужный результат.
спустя 1 час 5 минут [обр] Vladmir[досье]
Денис Гетман[досье]Вы могли бы пример с having написать?.. Мне думается не пройдет: В where будет ругаться на агрегативность, а в having - ... то же... Просто интересно.
спустя 2 часа 8 минут [обр] Lynn «Кофеман»(0/571)[досье]
Выборка записей по дате (285172)
Вроде оно же с помощью LEFT JOIN.
спустя 2 часа 17 минут [обр] Денис Гетман(5/228)[досье]
 Что-то не соображу - таблица ведь всего одна? И никаких условий на число записей?
SELECT name, admat, max(_UPDTIME) 
FROM ... 
GROUP BY name, admat;
спустя 56 минут [обр] Vladmir[досье]
Точно. Ведь утром такой же запрос, но с ошибкой написал! Поэтому пришлось переписать через вложенный. День видимо не тот выдался...
спустя 6 часов [обр] Lynn «Кофеман»(0/571)[досье]
Денис Гетман[досье]
Таким способом можно только выяснить время последнего обновления, обычно же требуется получить всю строку или какие-то другие уникальные данные присущие этой строке. Поэтому группировка никак нам не помогает.
спустя 6 часов [обр] Роман Чемисов(0/350)[досье]
Денис Гетман[досье]
Как сказал уже Lynn «Кофеман»[досье] Вас запрос не подходит. Он вычисляет правильное время обновления, но данные (name) берёт из другой записи (не той, для которой max(_UPDTIME).
Powered by POEM™ Engine Copyright © 2002-2005