RuNTiME
|
|
« : 08-03-2009 15:52 » |
|
в общем задача в следующем, создать справочник(таблицу), который хранит историю изменения записей по датам. 1. На входе REC_ID записи и дата актуальности(ACTUAL_DATE) записи. На выходе запись актуальная на заданную дату 2. На входе дата актуальности(ACTUAL_DATE). На выходе список(актуальных) не закрытых записей на эту дату. В качестве СУБД использую MySQL. Для экспериментов создал вот такую таблицу: +----+--------+-------------+------------+ | ID | REC_ID | ACTUAL_DATE | CLOSE_DATE | +----+--------+-------------+------------+ | 1 | 1 | 1 | 10 | | 2 | 1 | 2 | 10 | | 3 | 1 | 3 | 10 | | 4 | 1 | 4 | 10 | | 5 | 1 | 5 | 10 | | 6 | 1 | 6 | 10 | | 7 | 1 | 7 | 10 | | 8 | 1 | 8 | 10 | | 9 | 1 | 9 | 10 | | 10 | 1 | 10 | 10 | | 11 | 11 | 10 | 0 | | 12 | 11 | 15 | 0 | | 13 | 11 | 16 | 0 | | 14 | 11 | 17 | 17 | +----+--------+-------------+------------+
Описание полей: ID - первичный ключ REC_ID - уникальный ID записи, присваиваетя при первом вводе записи методом копирования из поля ID. При изменении записи он дублируется. ACTUAL_DATE - дата изменения записи CLOSE_DATE - дата закрытия или окончания действия записи, если = 0, то срок не ограничен (пока не будет закрыта). Если с первой задачей еще получилось справиться вот таким образом: SELECT * FROM test WHERE REC_ID = <ID записи> AND ACTUAL_DATE = (SELECT MAX(ACTUAL_DATE) FROM test WHERE REC_ID = <ID записи> AND ACTUAL_DATE <= <дата актуальности>);
то вторую решить пока не удалось очень жду ваших советов
|
|
« Последнее редактирование: 08-03-2009 15:55 от RuNTiME »
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 08-03-2009 16:22 » |
|
прочитал несколько раз, не понял оба задания скажи словами, что требуется достичь ?
|
|
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #2 : 08-03-2009 16:48 » |
|
Алексей1153++, суть в чем, есть к примеру справочник сотрудников. Кто-то приходит, кто-то увольняется. В таблице которую я привел находиться история двух записей с REC_ID = 1 и REC_ID = 11. 1. Если я знаю что идентификатор сотрудника REC_ID = 1, а дата ACTUAL_DATE = 7, то получаю запись: +----+--------+-------------+------------+ | ID | REC_ID | ACTUAL_DATE | CLOSE_DATE | +----+--------+-------------+------------+ | 7 | 1 | 7 | 10 | +----+--------+-------------+------------+
т.е. если говорить "человеческим" языком я знаю ID сотрудника и дату, то могу узнать работал он у меня в эту дату или нет. 2.Необходимо получить список всех сотрудников, работавших на какую либо дату. К примеру хочу узнать какие записи были актуальны на число ACTUAL_DATE = 10. На выходе должно быть следующее, если учитывать что сотрудник с REC_ID=1 еще работал в дату 10 (был его последний день т.к. CLOSE_DATE=10): +----+--------+-------------+------------+ | ID | REC_ID | ACTUAL_DATE | CLOSE_DATE | +----+--------+-------------+------------+ | 10 | 1 | 10 | 10 | | 11 | 11 | 10 | 0 | +----+--------+-------------+------------+
Все даты предполагаю хранить в TimeStamp формате, по этому и привожу в примерах числа.
|
|
« Последнее редактирование: 08-03-2009 16:53 от RuNTiME »
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #3 : 08-03-2009 17:51 » |
|
2) select distinct ID, REC_ID, ACTUAL_DATE, CLOSE_DATE from TEST where ACTUAL_DATE<=10 OR CLOSE_DATE=10
так?
|
|
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #4 : 08-03-2009 17:58 » |
|
Алексей1153++, что - то не то Вот ответ на твой запрос: +----+--------+-------------+------------+ | ID | REC_ID | ACTUAL_DATE | CLOSE_DATE | +----+--------+-------------+------------+ | 1 | 1 | 1 | 10 | | 2 | 1 | 2 | 10 | | 3 | 1 | 3 | 10 | | 4 | 1 | 4 | 10 | | 5 | 1 | 5 | 10 | | 6 | 1 | 6 | 10 | | 7 | 1 | 7 | 10 | | 8 | 1 | 8 | 10 | | 9 | 1 | 9 | 10 | | 10 | 1 | 10 | 10 | | 11 | 11 | 10 | 0 | +----+--------+-------------+------------+
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #5 : 08-03-2009 18:21 » |
|
а, ну дык тогда : ...... ACTUAL_DATE=10 .....
|
|
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #6 : 08-03-2009 18:26 » |
|
Алексей1153++, выдаёт тот же самый набор, что и прошлый запрос у тебя условие ACTUAL_DATE и CLOSE_DATE соединены через или....
|
|
« Последнее редактирование: 08-03-2009 18:28 от RuNTiME »
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #7 : 08-03-2009 18:35 » |
|
Алексей1153++, выдаёт тот же самый набор, что и прошлый запрос
если ACTUAL_DATE РАВНО 10 , то никак не получится, что в выборке будут ACTUAL_DATE со значенем меньше 10. а с CLOSE_DATE наверное надо убрать ? Я по заданию не совсем понял всё таки
|
|
« Последнее редактирование: 08-03-2009 18:37 от Алексей1153++ »
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #8 : 08-03-2009 18:38 » |
|
Алексей1153++, Запрос: select distinct ID, REC_ID, ACTUAL_DATE, CLOSE_DATE from test where ACTUAL_DATE=10 OR CLOSE_DATE=10; Ответ: +----+--------+-------------+------------+ | ID | REC_ID | ACTUAL_DATE | CLOSE_DATE | +----+--------+-------------+------------+ | 1 | 1 | 1 | 10 | | 2 | 1 | 2 | 10 | | 3 | 1 | 3 | 10 | | 4 | 1 | 4 | 10 | | 5 | 1 | 5 | 10 | | 6 | 1 | 6 | 10 | | 7 | 1 | 7 | 10 | | 8 | 1 | 8 | 10 | | 9 | 1 | 9 | 10 | | 10 | 1 | 10 | 10 | | 11 | 11 | 10 | 0 | +----+--------+-------------+------------+
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
RuNTiME
|
|
« Ответ #9 : 08-03-2009 18:41 » |
|
Алексей1153++, Насчет CLOSE_DATE это дата деактивации записи. т.е. дата после которой запись считается не актуальной. Возможно, что запрос удастся составить и без неё, сам пока не знаю. Но в программе это поле будет необходимо.
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #10 : 08-03-2009 18:43 » |
|
тогда так ( с AND CLOSE_DATE<=10;)
select distinct ID, REC_ID, ACTUAL_DATE, CLOSE_DATE from test where ACTUAL_DATE=10 AND CLOSE_DATE<=10;
|
|
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #11 : 08-03-2009 18:49 » |
|
Алексей1153++, да, это почти правильно В дату 10 выдает правильный результат: +----+--------+-------------+------------+ | ID | REC_ID | ACTUAL_DATE | CLOSE_DATE | +----+--------+-------------+------------+ | 10 | 1 | 10 | 10 | | 11 | 11 | 10 | 0 | +----+--------+-------------+------------+
Но если указать к примеру дату 11, то результат должен быть таким же как и для 10 т.к. не используем CLOSE_DATE. Твой запрос в дату 11 выдаёт пустой результат.
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
RuNTiME
|
|
« Ответ #12 : 08-03-2009 18:52 » |
|
Алексей1153++, я почти уверен, что надо использовать MAX(ACTUAL_DATE), но не получается её по - нормальному прикрутить...
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #13 : 08-03-2009 19:08 » |
|
тогда мысль такая: NNN=11 select distinct ID, REC_ID, ACTUAL_DATE, CLOSE_DATE from test where REC_ID = ... AND ACTUAL_DATE= (select max(ACTUAL_DATE) from test where ACTUAL_DATE<=:NNN ) кстати, непонятно, почему у тебя CLOSE_DATE=0 тоже в результате, или 0 означает, что поле не заполнено ? тогда select distinct ID, REC_ID, ACTUAL_DATE, CLOSE_DATE from test where REC_ID = ... AND (ACTUAL_DATE<=CLOSE_DATE OR CLOSE_DATE=0) AND ACTUAL_DATE= (select max(ACTUAL_DATE) from test where ACTUAL_DATE<=:NNN )
|
|
« Последнее редактирование: 08-03-2009 19:17 от Алексей1153++ »
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #14 : 08-03-2009 19:24 » |
|
Алексей1153++, насчет поля CLOSE_DATE я писал выше... если оно = 0, значит на тот момент было не известно, когда будет закрыта запись. Твои запросы ща попробую
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #15 : 08-03-2009 19:35 » |
|
невнимательное я ((
Кстати, надо ещё предусмотреть случай, когда подзапрос вернёт NULL
|
|
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #16 : 08-03-2009 19:37 » |
|
Алексей1153++, сенкс, вроде получилось, буду еще тестить..... только из твоего запроса надо кое - что убрать: REC_ID = ...вот запрос который дал верный результат на любой дате: select distinct ID, REC_ID, ACTUAL_DATE, CLOSE_DATE from test where (ACTUAL_DATE<=CLOSE_DATE OR CLOSE_DATE=0) AND ACTUAL_DATE= (select max(ACTUAL_DATE) from test where ACTUAL_DATE<=10 );
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
RuNTiME
|
|
« Ответ #17 : 08-03-2009 19:42 » |
|
Алексей1153++, кстати distinct в запросе тоже лишний.... select distinct ID дает тот же результат, что и просто select ID, т.к. поле ID это первичный ключ и никогда не повторяется еще раз сенкс за запрос, пол дня сегодня голову ломал над этой заразой
|
|
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #18 : 08-03-2009 19:45 » |
|
RuNTiME, ну я же не знаю, может ты решишь без ID вынимать данные Ну а так да, не нужно
|
|
|
Записан
|
|
|
|
RuNTiME
|
|
« Ответ #19 : 08-03-2009 20:39 » |
|
Алексей1153++, кстати пытаюсь оптимизировать твой запрос... условие (ACTUAL_DATE<=CLOSE_DATE OR CLOSE_DATE=0) тоже оказалось лишним... ACTUAL_DATE никогда не будет больше CLOSE_DATE т.к. запись не может изменяться после даты закрытия.... а раз отпадает условие ACTUAL_DATE<=CLOSE_DATE, то можно выкинуть и вторую часть CLOSE_DATE=0. И все продолжает работать отлично В итоге осталось: select * from test where ACTUAL_DATE=(select max(ACTUAL_DATE) from test where ACTUAL_DATE<=10);
А так можно еще и закрытые записи отфильтровать: select * from test where (CLOSE_DATE>=<дата> or CLOSE_DATE=0) AND ACTUAL_DATE=(select max(ACTUAL_DATE) from test where ACTUAL_DATE<=<дата> );
|
|
« Последнее редактирование: 08-03-2009 20:55 от RuNTiME »
|
Записан
|
Любимая игрушка - debugger ...
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #20 : 08-03-2009 20:59 » |
|
RuNTiME, учти, что бывают ошибки заполнения базы, даже если там будут триггеры вставки (всякое бывает), так что от греха подальше не убирай эти условия.
|
|
|
Записан
|
|
|
|
|