Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Запрос, как найти соседние строки? / 25 сообщений из 28, страница 1 из 2
19.09.2015, 15:07
    #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
19.09.2015, 15:24
    #39055984
sdepals
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрос, как найти соседние строки?
И да ньюанс ) параметр типа date поле типа datetime и соответственно в течении дня несколько записей может быть.
...
Рейтинг: 0 / 0
19.09.2015, 15:46
    #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
19.09.2015, 16:29
    #39056024
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрос, как найти соседние строки?
sdepalsпараметр типа date поле типа datetime и соответственно в течении дня
несколько записей может быть.
И сколько из этих записей ты хочешь получить?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
19.09.2015, 17:05
    #39056046
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрос, как найти соседние строки?
sdepals,

и сколько таких записей может быть - за день, за год? Есть вообще смысл вычислять Max, если известно, что ЗАВТРА пациента все равно еще нигде нет, потому что оно не наступило? Есть ли смысл вычислять дату первого поступления?
Может быть, просто выдать все записи, а дальше фильтровать локально "снизу вверх и сверху вниз..."?
...
Рейтинг: 0 / 0
19.09.2015, 18:06
    #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
19.09.2015, 18:26
    #39056124
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрос, как найти соседние строки?
Вот так неудачная структура БД доставляет проблем разработчикам приложений.
Всё было бы гораздо проще, если бы пребывание пациента в отделении контролировалось
таблицей с полями ("поступил в отделение", "отбыл с отделения").

А так тебе прямая дорога к Execute Block или хранимой процедуре.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
19.09.2015, 18:43
    #39056142
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрос, как найти соседние строки?
sdepalsТаблоид, индексы то есть, но только твой запрос не вернет то что надо :(да, не вернёт: я забыл в скалярные подзапросы добавить условие по owner.id.
А ты привёл DDL таблицы, но забыл/поленился привести пример данных, в виде insert'ов (ИБЭ это позволяет сделать в полпинка). Давай сюда 10-15 строк, тогда проще будет понять, что там.
...
Рейтинг: 0 / 0
19.09.2015, 19:51
    #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
19.09.2015, 20:04
    #39056192
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрос, как найти соседние строки?
sdepalsесли делать столбцы "прибыл" "убыл" то надо и другие столбцы тянуть совсем
необязательные для всех строк
Зачем? Третью НФ нынче отменили?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
19.09.2015, 20:42
    #39056220
sdepals
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрос, как найти соседние строки?
Меня конечно больше САБЖ интересует, но это я хотел спросить как это связано с 3НФ? )

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


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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

Поддерживающие оконные функции?
...
Рейтинг: 0 / 0
30.09.2015, 17:07
    #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
01.10.2015, 09:43
    #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
01.10.2015, 10:05
    #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
01.10.2015, 10:18
    #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
01.10.2015, 12:12
    #39065992
afgm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Запрос, как найти соседние строки?
WildSeryВопрос неправильный, одиночная запись находится легко.
А вот найти сразу для таблицы дат, для разных сотрудников - вот тут уже начинаются треугольные велосипеды.
Ну зачем же так сразу. Я планировал вывести на это автора поста не с первой итерации :)
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Запрос, как найти соседние строки? / 25 сообщений из 28, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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