Выберите максимальное значение в диапазоне дат

Задача:

  • Добавьте/отредактируйте текущий рабочий код ниже, чтобы возвратить только одну строку для каждого пациента, максимальное значение d1_10.xtransfer (тип данных int) с ограничением d1_10.dstartdate <= glob_End_Date этой строки.

Предупреждения:

  • Подобные вопросы есть на StackOverflow и родственных сайтах. Ни один из тех, что я нашел, не помог с решением этой проблемы.

  • Это медицинская база данных EHR, я могу поделиться кодом, но любое обсуждение результатов должно быть общим и исключать информацию о пациентах.

  • Я заменяю SQL-запрос в уже существующей электронной таблице Excel, чтобы сделать что-то другое. Excel извлекает информацию из нашей базы данных через соединение ODBC. Наша база данных использует Ingres SQL, который принимает большинство, но не все типичные варианты кода SQL. Вполне возможно, что фрагмент кода будет работать в других вариантах SQL, но не с комбинацией Ingres и Excel. У меня есть электронная таблица, работающая и возвращающая результаты, теперь нужно внести некоторые исправления, написав код SQL, который работает в этом программном обеспечении.

На данный момент:

С приведенным ниже рабочим кодом (без максимальных ограничений d1_10.xtransfer) мы возвращаем все строки с d1_10.dstartdate в выбранном пользователем диапазоне дат и с выбранным пользователем d1_10.xinstitute. Мы хотим только самую последнюю. То есть строка пациента либо с максимальным d1_10.dstartdate в пределах диапазона дат, либо с максимальным d1_10.xtransfer (индекс, который увеличивается по мере их добавления) в пределах диапазона дат.

В настоящее время рабочий код:

    "SELECT " & _
    "d1.xpid ""XPID"", " & _
    "d0_v1.name_family ""NAME_FAMILY"", " & _
    "d0_v1.name_given1 ""NAME_GIVEN1"", " & _
    "d0_v1.name_given2 ""NAME_GIVEN2"", " & _
    "d1.sex ""SEX"", " & _
    "d1.birthdate ""DOB"", " & _
    "d0_v1.hsp_pid, " & _
    "c58.brief_name, " & _
    "c73.cname, " & _
    "date_trunc('day',d1_10.dstartdate) ""DSTARTDATE"", " & _
    "date_trunc('day',d1_17.ddeath) ""DDEATH"" " & _
    "FROM d1 " & _
    "JOIN d0_v1 ON d1.xpid = d0_v1.xpid " & _
    "JOIN d1_2 ON d1.xpid = d1_2.xpid  " & _
    "JOIN c58 ON d1_2.xmodality = c58.xcmodality " & _
    "JOIN d1_10 ON d1.xpid = d1_10.xpid " & _
    "JOIN c73 ON d1_10.xinstitute = c73.xcsite " & _
    "JOIN d1_17 ON d1.xpid = d1_17.xpid " & _
    "WHERE " & _
    "d1_10.xinstitute = " & institute_index & " AND " & _
    "d1_10.dstartdate >= '" & glob_Start_Date & " 00:00:00' and " & _
    "d1_10.dstartdate <= '" & glob_End_Date & " 23:59:59' "

Самое близкое, что я получил с кодом, который запускается из электронной таблицы Excel, это с этой дополнительной строкой в ​​предложении WHERE:

d1_10.xtransfer = (SELECT MAX(d1_10.xtransfer) FROM d1_10 GROUP BY xpid)

С помощью этой дополнительной строки мы теперь возвращаем только одну строку от каждого пациента, у которого есть d1_10.xtransfer в диапазоне дат. Но если у них есть строка, где d1_10.xtransfer является более поздним, чем диапазон дат, то они вообще не отображаются в результатах.

В этой строке код принимает MAX(d1_10.xtransfer) для каждого xpid, прежде чем применяет ограничение даты. По моей логике, мы хотим, чтобы это было сделано после, но я не смог придумать код, который работает, чтобы приблизиться к этому.

Заранее спасибо. Я буду обновлять этот вопрос, добавляя дополнительную информацию ниже этого разрыва страницы.


Дополнительная информация:

  • По Полу М:

Да, xpid — это идентификационный номер пациента, уникальный для каждого пациента.

Добавлена/изменена строка в предложении WHERE на: "d1_10.xtransfer = (SELECT MAX(xtransfer) FROM d1_10 d1_10_b WHERE d1_10.xpid = d1_10_b.xpid AND d1_10_b.dstartdate <= '" & glob_End_Date & " 23:59:59') "

У пациента Боба есть переводы 14 и 17 июня, которые соответствуют остальным критериям.

При вводе диапазона дат с датой окончания 17 июня и старше электронная таблица правильно возвращает строку для Боба с его переводом 17 июня.

При вводе диапазона дат с конечной датой 14, 15 или 16 июня электронная таблица неправильно не возвращает строку для Боба.

Кажется, что он по-прежнему требует максимального xtransfer перед ограничением по дате.

  • По комментарию PaulM:

Я выполнил подвыборку для конкретного пациента следующим образом:

Вход:

SELECT MAX(xtransfer) FROM d1_10 d1_10_b WHERE d1_10_b.xpid = '2258' AND d1_10_b.dstartdate <= '20-apr-2016 23:59:59'

Он вывел значение MAX(xtransfer) = '48233'. Это правильно.

Таким образом, при запуске в Visual SQL в качестве собственного оператора, устанавливая d1_10_b.xpid равным конкретному пациенту, он правильно извлекает максимальный xtransfer из диапазона дат. (Было более свежее xtransfer за пределами диапазона дат, и оно по-прежнему правильно отображало максимальное xtransfer в пределах диапазона дат.)

Затем я попытался запустить этот же самый подвыбор в том месте, где закрывается электронная таблица. То есть я вручную выбрал тот же диапазон дат (который корректно и успешно передается как переменная), но заменил d1_10.xpid = d1_10_b.xpid на d1_10_b.xpid = '2258'. Это не сработало. Электронная таблица не показала строку для этого пациента, по-видимому, потому, что она по-прежнему применяет функцию MAX() до ограничения диапазоном дат в подзапросе. И все же подзапрос работает, когда он запускается сам по себе.

Большое спасибо за любые дальнейшие предложения.


person Jackson    schedule 07.07.2016    source источник


Ответы (1)


Вам нужно добавить ограничение даты в подзапросе, а также в основном запросе. Также я подозреваю, что группа неверна. Добавляя группу, вы делаете подвыбор списка значений xtransfer пациентов с наибольшим значением для каждого xpid (идентифицирует пациента?). Однако это означает, что если интересующая вас строка из основного запроса имеет значение xtransfer, которое соответствует наибольшему значению, принадлежащему другому xpid, вы получаете ложное совпадение.

Что вам действительно нужно, так это добавить соединение по xpid из резервной копии подзапроса к основному запросу. Для этого вам понадобится другое корреляционное имя, например.

d1_10.xtransfer = (SELECT MAX(xtransfer) 
                   FROM d1_10 d1_10_b 
                   WHERE d1_10.xpid = d1_10_b.xpid 
                   AND d1_10_b.dstartdate > = ... {as above} )
person PaulM    schedule 07.07.2016
comment
Спасибо, что вложили некоторые мысли в это. Я попробовал этот код, я согласен с логикой, но вывод по-прежнему неправильно ограничивается датой. См. редактирование в разделе «Дополнительная информация» для получения результатов. Заранее благодарим за любую постоянную помощь в устранении неполадок. - person Jackson; 08.07.2016
comment
Не уверен, в чем проблема. В этот момент я бы попробовал пару вещей. 1) запустите подвыбор самостоятельно (с фактическим значением xpid для «Боба»), чтобы убедиться, что он возвращает правильный номер для xtransfer. 2) попробуйте весь запрос в мониторе терминала SQL. Это устраняет любые проблемы/ошибки с Excel и ODBC. Также, вероятно, стоит обратиться в техподдержку Actian. - person PaulM; 11.07.2016
comment
Спасибо, Пол. Меня нет на месте в начале этой недели, я дам вам знать, что я придумаю в середине недели. - person Jackson; 11.07.2016
comment
Пол, может быть, я приближаюсь? Добавил еще один раздел в дополнительную информацию. Подвыборка корректно работает в Visual SQL сама по себе для конкретного пациента, электронная таблица по-прежнему не работает с точно такой же конкретной подвыборкой. Определенно начинаю чувствовать себя сбитым с толку. - person Jackson; 13.07.2016
comment
Кажется, что логика выполняется по-разному при запуске в разных приложениях. Visual SQL выбирает максимальное значение из диапазона дат по желанию. Excel выбирает абсолютное максимальное значение, а затем проверяет, попадает ли выбранная строка в диапазон дат. По крайней мере, это лучшее, что я могу предположить. Итак, вы согласны, что моя задача сейчас действительно такова: как мы можем обмануть Excel, чтобы он логически обработал это правильно? - person Jackson; 13.07.2016