Выбор первой дочерней записи в самостоятельном соединении в TSQL - PullRequest
0 голосов
/ 24 февраля 2012

У меня есть таблица visits, которая выглядит следующим образом:

id identity(1,1) not null,
visit_date datetime not null,
patient_id int not null,
flag bit not null

Для каждой записи мне нужно найти совпадающую запись того же времени или раньше, с таким же значением Patient_id иflag имеет значение 1. Что я сейчас делаю:

select parent.id as parent_id, 
(
   select top 1 
      child.id as child_id
   from 
      visits as child
   where 
     child.visit_date <= parent.visit_date
     and child.patient_id = parent.patient_id
     and child.flag = 1
   order by 
     visit_date desc
 ) as child_id
from 
   visits as parent

Итак, этот запрос работает правильно, за исключением того, что он выполняется слишком медленно - я подозреваю, что это из-за подзапроса.Можно ли переписать его как объединенный запрос?

Ответы [ 2 ]

1 голос
/ 24 февраля 2012

Просмотр плана выполнения запроса. Там, где у вас толстые стрелки, посмотрите на эти утверждения. Вы должны изучить различные утверждения и то, что они подразумевают, например, что Clustered Index Scan / Seek и т.д.

Обычно, когда запрос идет медленно, я нахожу, что хороших индексов нет.

Таблицы и столбцы, затронутые и используемые для объединения, создают индекс, охватывающий все эти столбцы. Обычно это называется индексом покрытия на форумах. Это то, что вы можете сделать для чего-то, что действительно нуждается в этом. Но имейте в виду, что слишком много индексов замедляют операторы вставки.

0 голосов
/ 24 февраля 2012
   /* 
    id identity(1,1) not null,
    visit_date datetime not null,
    patient_id int not null,
    flag bit not null
   */

SELECT
    T.parentId,
    T.patientId,
    V.id AS childId
FROM
    (
    SELECT
        visit.id AS parentId,
        visit.patient_id AS patientId,
        MAX (previous_visit.visit_date) previousVisitDate
    FROM
        visit
        LEFT JOIN visit previousVisit ON
            visit.patient_id = previousVisit.patient_id
            AND visit.visit_date >= previousVisit.visit_date
            AND visit.id <> previousVisit.id
            AND previousVisit.flag = 1
    GROUP BY
        visit.id,
        visit.visit_date,
        visit.patient_id,
        visit.flag
    ) AS T
    LEFT JOIN visit V ON
      T.patientId = V.patient_id
      AND T.previousVisitDate = V.visit_date
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...