2013-08-23 1 views
0

Я рад, что на этот раз у меня есть вопрос, по крайней мере, на рабочем примере. Раньше это был эффективный запрос, когда у меня были только критерии, в которых результат был возвращен, если у него было count> = 1. Затем мне пришлось добавить счетчик для разных значений кода, и если они происходят 2 или более раз. Запрос продолжился от нескольких секунд до примерно 43 секунд.SQL Server: если одно значение в столбце встречается хотя бы один раз или другое значение более одного раза

Я думаю, что у меня есть логика, но мне было интересно, есть ли у кого-то более эффективный способ сделать это.

select person.person_id 
from person 
where 
person.person_id in (
     select procedure.person_id 
     from procedure 
     where 
     procedure.performed_by = '555555' 
     and procedure.code in (
       '99201', '99202' 
       ) 
     and year(procedure.service_date) = year(getdate()) 
     group by procedure.person_id 
     having count(1) >= '1' 
     ) -- having count >= 1 occurrences 
or person.person_id in (
     select person_id 
     from procedure 
     where 
     procedure.performed_by = '55555' 
     and code in (
       '99304','99305' 
       ) 
     and year(procedure.service_date) = year(getdate()) 
     group by procedure.person_id 
     having count(1) >= '2' 
     ) -- having count >= 2 occurrences 
+1

Спасибо за изменения, @marc_s! Я хотел сделать его доступным для поиска. это лучший источник для sql-информации, и я не хотел ограничивать его одной базой данных, потому что он довольно универсален. – jawz101

+0

Можете ли вы разместить некоторые примеры данных и ожидаемый результат на основе такого примера или, что еще лучше, создать 'SQL Fiddle' [sqlfidle.com]. Кажется, что ваш запрос может и должен быть оптимизирован. –

+0

Я все еще получаю зависание stackoverflow, и я начну использовать SQL Fiddle, поскольку это определенно помогает. Спасибо за ваш отзыв! – jawz101

ответ

1

Это ускоряет его?

WITH CTE AS 
(
    select procedure.person_id 
    from procedure 
    where 
    procedure.performed_by = '555555' 
    and procedure.code in ('99201', '99202') 
    and year(procedure.service_date) = year(getdate()) 
    group by procedure.person_id 
    having count(1) >= '1' 

    UNION 

    select person_id 
    from procedure 
    where 
    procedure.performed_by = '55555' 
    and code in ('99304','99305') 
    and year(procedure.service_date) = year(getdate()) 
    group by procedure.person_id 
    having count(1) >= '2' 
) 

select person.person_id 
from person 
JOIN CTE ON CTE.Person_id = Person.Person_Id 
+0

святой карп! Этот союз сократил его до 1 секунды. Мне действительно нужно научиться их использовать. Я объединил оба ваших исправления, чтобы очистить их и ускорить. Благодаря! – jawz101

+0

Мое удовольствие, очень рад, что смогу помочь :) –

1

Ваш первый IN просто проверка существования, так что нет никакой реальной необходимости использования HAVING (на другой ноте, почему вы сравнивая COUNT(1) со строкой ?, результатом является INT, так что вы должны использовать >=1 или >=2). Вы также используете функцию на service_date, прежде чем сравнивать ее, вы не должны этого делать, поскольку не можете использовать возможный индекс в этом столбце. Я хотел бы написать запрос следующим образом:

select p.person_id 
from person p 
where exists ( select 1 
       from procedure 
       where 
       procedure.performed_by = '555555' 
       and procedure.code in ('99201', '99202') 
       and procedure.service_date >= dateadd(year,datediff(year,0,getdate()),0) 
       and procedure.service_date < dateadd(year,datediff(year,0,getdate())+1,0) 
       and procedure.person_id = p.person_id) 
or person.person_id in (
     select person_id 
     from procedure 
     where 
     procedure.performed_by = '55555' 
     and code in ('99304','99305') 
     and procedure.service_date >= dateadd(year,datediff(year,0,getdate()),0) 
     and procedure.service_date < dateadd(year,datediff(year,0,getdate())+1,0) 
     group by procedure.person_id 
     having count(1) >= 2 
     ) -- having count >= 2 occurrences 
+0

спасибо, что помогли мне очистить мой запрос. Он выбрит на несколько секунд, избавившись от этого первого подсчета. Это огромная таблица, и в операторах in() есть еще несколько кодов, но для краткости я просто хотел показать, что их было несколько. Я думаю, что скорость неизбежна со вторым подсчетом, который должен произойти. – jawz101