powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Запрос, как найти соседние строки?
28 сообщений из 28, показаны все 2 страниц
Запрос, как найти соседние строки?
    #39055980
sdepals
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Помогите с запросом, свой select с 10 вложенными подзапросами непонравился )

Есть регистр движения пациента по отделениям поля owner - пациент, datedvig - дата/время движения.
Пользователь вводит параметр "Дата" и должен получить поля owner, max(datedvig) до параметра, min(datedvig) после параметра.
максимальную дату "до параметра" нашел, как прикрутить минимальную дату "после параметра"?

Код: sql
1.
2.
3.
select A.owner,max(A.datedvig) from dvig A
where A.datedvig<cast(:PARAM as Date)+1
group by A.owner



Firebird 2.5
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39055984
sdepals
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
И да ньюанс ) параметр типа date поле типа datetime и соответственно в течении дня несколько записей может быть.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39056000
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
select o.name
,(select d.datedvig  from dvig d where d.datedvig < cast(:param as date) order by d.datedvig desc rows 1) was_before_parameter_value
,(select d.datedvig  from dvig d where d.datedvig > cast(:param as date) order by d.datedvig rows 1) was_after_parameter_value
from owner o;



(только убедитесь, что на таблице 'dvig' висят два индекса - по возрастанию и убыванию поля datedvig).
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39056024
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sdepalsпараметр типа date поле типа datetime и соответственно в течении дня
несколько записей может быть.
И сколько из этих записей ты хочешь получить?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39056046
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sdepals,

и сколько таких записей может быть - за день, за год? Есть вообще смысл вычислять Max, если известно, что ЗАВТРА пациента все равно еще нигде нет, потому что оно не наступило? Есть ли смысл вычислять дату первого поступления?
Может быть, просто выдать все записи, а дальше фильтровать локально "снизу вверх и сверху вниз..."?
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39056102
sdepals
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну раз нужны подробности тогда так:

CREATE TABLE DRIVINGPATIENT (
OWNER KEYS NOT NULL /* KEYS = CHAR(16) */, -- Карта пациента
DATEON DATE_TIME NOT NULL /* DATE_TIME = TIMESTAMP */, --Дата и время движения
TYPE_DRIVING KEYS NOT NULL /* KEYS = CHAR(16) */,--Тип движения
DEPARTMENT KEYS /* KEYS = CHAR(16) */,--Отделение
);

Входящие параметры DEPARTMENT и DATEON

Запрос должен вернуть данные по пациентам находящимся в отделении на указанную дату.
Чтобы найти отделение пациента нужно найти для его карты(OWNER) последнее движение(max(DATEON)) с типом(TYPE_DRIVING)=1.

для пациента поступившего сегодня 19.09.2015 сделано 3 движения:
9:00 - TYPE_DRIVING=0 (направлен в отделение)
10:00 - TYPE_DRIVING=1 (поступил в отделение)
11:00 - TYPE_DRIVING=2 (Выписан)

на входной параметр по этому отделению DATEON=19.09.2015.

надо найти строчку "10:00 - TYPE_DRIVING=1 (поступил в отделение)" -нашли отделение где он был.
а потом найти первую следующую строчку с любым типом движения - "11:00 - TYPE_DRIVING=2 (Выписан)"

разница между этими датами это кол-во дней которые пациент провел в отделении.

Таблоид, индексы то есть, но только твой запрос не вернет то что надо :(

kdv, карт - много, движений в карте крайне сомнительно, что больше 10.
Max c типом движения = 1 вычисляется для поиска отделения, а вот запись MIN может отсутствовать, в зависимости находится ли пациент в отделении сейчас? Если еще не выписали записи MIN нет.
Отчёт может делаться на любую дату как на сегодня(где у текущих пациентов движения выписан нет), так и на год назад, где все выписаны.

P.S. насчёт выдать все записи, первое поле MAX это лишь подзапрос-фильтр для основного запроса по картам.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39056124
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот так неудачная структура БД доставляет проблем разработчикам приложений.
Всё было бы гораздо проще, если бы пребывание пациента в отделении контролировалось
таблицей с полями ("поступил в отделение", "отбыл с отделения").

А так тебе прямая дорога к Execute Block или хранимой процедуре.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39056142
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sdepalsТаблоид, индексы то есть, но только твой запрос не вернет то что надо :(да, не вернёт: я забыл в скалярные подзапросы добавить условие по owner.id.
А ты привёл DDL таблицы, но забыл/поленился привести пример данных, в виде insert'ов (ИБЭ это позволяет сделать в полпинка). Давай сюда 10-15 строк, тогда проще будет понять, что там.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39056189
sdepals
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Таблоид, не забыл и поленился, а структуру для упрощения резал) и сокращал):
и о ужас, про проблему одного дня знал, но сейчас до другого ньюанса дошел. более печального.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k1              ', '2015-09-18 09:00:00', '0               ', 'd1              ');
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k1              ', '2015-09-18 10:00:00', '1               ', 'd1              ');
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k1              ', '2015-09-18 11:00:00', '2               ', 'd1              ');
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k2              ', '2015-09-19 09:00:00', '0               ', 'd1              ');
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k2              ', '2015-09-19 10:00:00', '1               ', 'd1              ');
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k2              ', '2015-09-19 11:00:00', '2               ', 'd1              ');
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k3              ', '2015-09-18 09:00:00', '0               ', 'd1              ');
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k3              ', '2015-09-19 10:00:00', '1               ', 'd1              ');
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k3              ', '2015-09-20 11:00:00', '2               ', 'd1              ');
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k4              ', '2015-09-20 09:00:00', '0               ', 'd1              ');
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k4              ', '2015-09-20 10:00:00', '1               ', 'd1              ');
INSERT INTO DRIVINGPATIENT (OWNER, DATEON, TYPE_DRIVING, DEPARTMENT)
                    VALUES ('k4              ', '2015-09-20 11:00:00', '2               ', 'd1              ');



Входной параметр - 19.09.2015

k1 - поступил и выписан раньше - не подходит.
k2 - поступил сегодня и выписан сегодня - ПОДХОДИТ! Кол-во дней в отделении: 0
k3 - поступил сегодня выписан завтра - подходит. Кол-во дней: 1
k4 - поступил завтра = не подходит

Dimitry Sibiryakov, про структуру БД так каждый новоприбывший программист говорит )) и зачастую не по делу)), если делать столбцы "прибыл" "убыл" то надо и другие столбцы тянуть совсем необязательные для всех строк, да сами прибыл убыл тоже не обязательны, бывает все заканчивается движением "направлен" и неоформляемым движением "пошелнахертыздоров" т.е. в отделение он ни поступал и не выписывался) но направлялся)
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39056192
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sdepalsесли делать столбцы "прибыл" "убыл" то надо и другие столбцы тянуть совсем
необязательные для всех строк
Зачем? Третью НФ нынче отменили?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39056220
sdepals
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Меня конечно больше САБЖ интересует, но это я хотел спросить как это связано с 3НФ? )

Dimitry Sibiryakovтаблицей с полями ("поступил в отделение", "отбыл с отделения").


как запишешь в эти поля пациента1 который имеет одно движение "Направлен в отделение" поля "поступил в отделение", "отбыл с отделения" должны быть null,null

как запишешь второго пациента у которого 2 движения "Поступление в отделение" и "Перемещение внутри отделения" т.е. поступил но не отбыл, перемещение внутри отделения куда писать? новое поле лепить? Что-то поле "отбыл с отделения" как раз попахивает избыточностью не связанной с 3НФ. Хотя не видел еще ни одной БД где бы не жертвовали 3НФ ради удобства писать запросы и производительности.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39056258
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sdepalsя хотел спросить как это связано с 3НФ? )
Напрямую: тащить в таблицу истории нахождения пациента в отделении левые поля с тем, чтобы
дублировать информацию в них - нарушение этой НФ.

sdepalsкак запишешь в эти поля пациента1 который имеет одно движение "Направлен в
отделение"
Никак. Он не был в отделении вообще.

sdepalsкак запишешь второго пациента у которого 2 движения "Поступление в
отделение" и "Перемещение внутри отделения" т.е. поступил но не отбыл,
Так и запишу: "поступил тогда-то" и "никогда не отбыл". То, что его с койки на койку
переложили не меняет факта нахождения в отделении, который и отображается в твоём отчёте.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39056270
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

мне кажется, тут исходно была попытка какого-то документооборота. А так, действительно, вроде д.б. таблица
пациент, отделение, прибыл, убыл.
А что с пациентом происходило в отделении (или вообще) - отдельная таблица.

Впрочем, возможно что зря я влез, но исходное сообщение уже сразу намекало, что в структуре что-то не так.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39057707
zeon11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sdepalsМеня конечно больше САБЖ интересует, но это я хотел спросить как это связано с 3НФ? )

Dimitry Sibiryakovтаблицей с полями ("поступил в отделение", "отбыл с отделения").


как запишешь в эти поля пациента1 который имеет одно движение "Направлен в отделение" поля "поступил в отделение", "отбыл с отделения" должны быть null,null

как запишешь второго пациента у которого 2 движения "Поступление в отделение" и "Перемещение внутри отделения" т.е. поступил но не отбыл, перемещение внутри отделения куда писать? новое поле лепить? Что-то поле "отбыл с отделения" как раз попахивает избыточностью не связанной с 3НФ. Хотя не видел еще ни одной БД где бы не жертвовали 3НФ ради удобства писать запросы и производительности.

Перемещение внутри отделения, это как?
Из одной палаты в другую, или в реанимацию?
Тогда надо атомарить не отделения, а все возможные точки нахождения пациентов. И да,
"время прибыл в точку" - "время убыл с точки", как уже написал Dimitry Sibiryakov.
Если "время убыл" null, то пациент находится в текущий момент времени в этой точке,
если надо найти, где был пациент неделю назад, то ищем запись с требуемыми границами.
Точки естественно подчинены отделениям больницы, другим больницам, в качестве точек могут выступать операционные, транспортные средства, собственный дом пациента и т.д.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39058258
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sdepalsХотя не видел еще ни одной БД где бы не жертвовали 3НФ ради удобства писать запросы и производительности.
Ну это лишь значит, что не видел :)
Такие таблицы перемещений возникают постоянно. И постоянно люди пишут к ним многоэтажные запросы, чтобы всего лишь понять: "Был он там или нет в интересующее нас время?". Проходит время, а с ним приходит осознание. И добавление столбца с датой ухода из данного статуса сразу облегчает жизнь.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39063673
NikolayV81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
afgmИ постоянно люди пишут к ним многоэтажные запросы, чтобы всего лишь понять

От БД сильно зависит, если с этими запросами проблемы, то варианта всего 2 - неверная архитектура или неверный выбор БД.

p.s. Никто не мешает ещё и parent_id (id_income по аналогии со складом ) для операций перемещения использовать.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39063681
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sdepalsно это я хотел спросить как это связано с 3НФ?
А так, что человек может одновременно находиться только в одном месте. И в этом месте он находится от времени D1 (timestamp) до времени D2 (timestamp). При этом D2 может быть Null, если человек еще не переместился из этого места.

Если же человек получает направление, куда-то, то это является бумажкой, или вектором, т.е. свойством бумажки, которая получена в момент D3. И D3 вовсе не является свойством человека. Бумажку он получил в 8 утра, а переместился в отделение - в 9 утра.
И т.д. У вас в таблицу ради экономии связаны события, имеющие разные типы. Сейчас вы выкручиваетесь из ситуации, когда начало и конец события разнесены по 2м разным записям. Если вы добавите столбец timestamp в эту таблицу, тогда будете выкручиваться из другой ситуации, потому что у события "получил направление" нет окончания.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39063682
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kdv,

что-то я ответил на старое сообщение, извините, зачитался.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39064134
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NikolayV81afgmИ постоянно люди пишут к ним многоэтажные запросы, чтобы всего лишь понять

От БД сильно зависит, если с этими запросами проблемы, то варианта всего 2 - неверная архитектура или неверный выбор БД.

p.s. Никто не мешает ещё и parent_id (id_income по аналогии со складом ) для операций перемещения использовать.
Я вот такой СУ БД не знаю, где можно это легко разрулить не переписывая структуры или не создавая дополнительных объектов.
Поделитесь? :)
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39065334
NikolayV81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
afgm,

Поддерживающие оконные функции?
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39065445
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NikolayV81Поддерживающие оконные функции?
Скрипт
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
create table movements (
  id int,
  user_id int,
  place_id int,
  date_from timestamp
)

insert into movements (id, user_id, place_id, date_from)
  values (1, 1, 1, '2015-09-01 9:00');
insert into movements (id, user_id, place_id, date_from)
  values (1, 1, 2, '2015-09-02 9:00');
insert into movements (id, user_id, place_id, date_from)
  values (1, 1, 3, '2015-09-03 9:00');
insert into movements (id, user_id, place_id, date_from)
  values (1, 1, 4, '2015-09-04 9:00');
insert into movements (id, user_id, place_id, date_from)
  values (1, 1, 5, '2015-09-05 9:00');
insert into movements (id, user_id, place_id, date_from)
  values (1, 1, 6, '2015-09-06 9:00');
insert into movements (id, user_id, place_id, date_from)
  values (1, 1, 7, '2015-09-07 9:00');



Как узнать где был пользователь user_id =1 в '2015-09-05 15:00'?
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39065802
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
afgm,

Код: sql
1.
2.
3.
4.
select first 1 place_id
  from movements
  where user_id = 1 and date_from <= timestamp '2015-09-05 15:00'
  order by date_from desc



Вопрос неправильный, одиночная запись находится легко.
А вот найти сразу для таблицы дат, для разных сотрудников - вот тут уже начинаются треугольные велосипеды.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39065817
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
WildSeryА вот найти сразу для таблицы дат, для разных сотрудников - вот тут уже начинаются треугольные велосипеды.

с оконными функциями колёса покруглей будут

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
WITH T AS (
SELECT
    ID,
    PLACE_ID,
    USER_ID,
    DATE_FROM,
    FIRST_VALUE(PLACE_ID) OVER(PARTITION BY USER_ID ORDER BY DATE_FROM DESC) AS FIRST_PLACE_ID
FROM
    MOVEMENTS
WHERE DATE_FROM <= TIMESTAMP '2015-09-05 15:00')
SELECT
    ID,
    PLACE_ID,
    USER_ID,
    DATE_FROM
FROM T
WHERE PLACE_ID = FIRST_PLACE_ID
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39065829
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

Это только для разных сотрудников.
А теперь для разных дат попробуй.

Пусть так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
create table ass_injections (
  id int,
  user_id int,
  date_injection timestamp,
  vaccination_type int
);

insert into ass_injections (id, user_id, date_injection, vaccination_type)
  values (1, 1, '2015-09-02 13:00', 1);
insert into ass_injections (id, user_id, date_injection, vaccination_type)
  values (2, 1, '2015-09-03 13:00', 1);
insert into ass_injections (id, user_id, date_injection, vaccination_type)
  values (3, 1, '2015-09-06 13:00', 2);



Цель санитара - составить отчёт о местах где больного настиг очередной укол.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39065992
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
WildSeryВопрос неправильный, одиночная запись находится легко.
А вот найти сразу для таблицы дат, для разных сотрудников - вот тут уже начинаются треугольные велосипеды.
Ну зачем же так сразу. Я планировал вывести на это автора поста не с первой итерации :)
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39066006
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисс оконными функциями колёса покруглей будут
Имелось виду нечто вида
Код: sql
1.
2.
3.
4.
5.
6.
7.
with A as (
  select
    m.*, lead(date_from) over(partition by user_id order by date_from) as to_date
    from movements m
)
select * from A
  where user_id = 1 and date_from <= '2015-09-05 15:00' and '2015-09-05 15:00' < to_date


?
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39066045
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
afgm,

имелось ввиду именно то, что я написал. В твоём варианте предикаты не будут проталкиваться внутрь CTE, что обречёт на FULL SCAN таблицы movements даже при наличии любых индексов. Фильтр для user_id я не ставил потому, что надо для каждого сотрудника вывести было.

Хотя чисто в теории user_id мог бы проталкиваться внутрь для данного конкретного случая, т.к. не влияет на конечный результат. Но в FB оптимизатор пока ещё не достаточно умён и приходится самому запихивать его внутрь CTE.

Вторую задачку с уколами уже так легко не решить. По крайней мере эффективно решить весьма затруднительно.
...
Рейтинг: 0 / 0
Запрос, как найти соседние строки?
    #39066072
afgm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисимелось ввиду именно то, что я написал.
На самом деле цель понятна, но под каждый случай нужен свой запрос.
Наличие рассчитанного to_date позволяет всегда индексироваться и выполнять веселее.
А ещё to_date для последней даты удобно держать в виде 31.12.2999, дабы не играться с null-ами.
Ну и prev_state_id, prev_record_id материализовать уже по случаю.
Запросы такие часты, и каждый раз городить огород...
В FB нет параметризованных вьюшек, значит CTE-всегда.
...
Рейтинг: 0 / 0
28 сообщений из 28, показаны все 2 страниц
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Запрос, как найти соседние строки?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]