1

У меня есть процедура, которая подсчитывает счет и общую стоимость за каждый месяц.SQL WHERE clause as JOIN query

Теперь мне нужно передать дополнительный параметр @HasObservation в качестве дополнительного параметра. Логика для фильтрации - это не просто обычный фильтр поля. Его необходимо отфильтровать, присоединившись к другой таблице PatientXObservation. Если в этой таблице есть записи для значения 1,2,4, то только фильтровать эти заказы.

@ HasObservation = 1 среднее, FETCH RECORDS удовлетворяет этому условию

PatientXObservation O ON B.PatientId = O.PatientId 
     AND O.ObservationId IN (1,2,4) 

Как добавить этот фильтр в ниже SQL? Я не уверен, о том, как добавить это здесь

CREATE PROCEDURE [dbo].[GetDoctorOperationReportTest] 
(@IncludeVAT BIT = 0, @HasObservation BIT = 0) 
AS 
BEGIN 
    SET NOCOUNT ON  

    SELECT 
     YEAR(StartTime) [Year] 
     , MONTH(StartTime) [Month] 
     , COUNT(BookingId) [BookingCount] 
     , SUM(CASE 
      WHEN IsVAT = 1 AND @IncludeVAT = 1 
      THEN (Price/100) * 80 
      ELSE Price 
      END) AS TotalPrice 
     , C.CategoryId 
     , CategoryName 
    FROM Category c 
    LEFT JOIN Booking B ON C.CategoryId = B.CategoryId 
    WHERE 
     C.IncludeReport = 1 
    GROUP BY YEAR(StartTime), MONTH(StartTime), C.CategoryId, CategoryName 
    ORDER BY 1, 2, CategoryName 
END 

Я попытался с TEMP таблицы, но запрос выполняется очень очень медленно. Другой вопрос здесь, если @HasObservation является 0, мне нужно, чтобы избежать этого фильтра, но, к сожалению, он выбирает наблюдение = 0 :(

SELECT B.BookingId 
    ,B.StartTime 
    ,B.IsVAT 
    ,B.Price 
    ,c.CategoryId 
    ,c.CategoryName 
    ,c.IncludeReport 
    ,observation = (
     CASE 
      WHEN isnull(o.PatientId, 0) = 0 
       THEN 0 
      ELSE 1 
      END 
     ) 
INTO #Temp 
FROM Category c 
LEFT JOIN Booking B ON C.CategoryId = B.CategoryId 
LEFT JOIN PatientXObservation O ON B.PatientId = O.PatientId 
    AND O.ObservationId IN (1,2,4) 



SELECT YEAR(StartTime) [Year] 
    ,MONTH(StartTime) [Month] 
    ,COUNT(BookingId) [BookingCount] 
    ,SUM(CASE 
      WHEN IsVAT = 1 
       AND @IncludeVAT = 1 
       THEN (Price/100) * 80 
      ELSE Price 
      END) AS TotalPrice 
    ,CategoryId 
    ,CategoryName 
FROM #Temp 
WHERE IncludeReport = 1 
    AND observation = @HasObservation 
GROUP BY YEAR(StartTime) 
    ,MONTH(StartTime) 
    ,CategoryId 
    ,CategoryName 
ORDER BY 1 
    ,2 
    ,CategoryName 
+0

Подумайте о SELECT Вы могли бы использовать, чтобы просто вернуть все PatientId вы не заинтересованы, поскольку набор ключей. Затем вы можете использовать внешнее соединение, чтобы убедиться, что B.PatientId отсутствует в этом списке. – Biscuits

ответ

3

Вы можете использовать оператор IN для фильтрации, только если параметр @HasObservation не равен нулю:

SELECT 
    YEAR(StartTime) [Year] 
    , MONTH(StartTime) [Month] 
    , COUNT(BookingId) [BookingCount] 
    , SUM(CASE 
     WHEN IsVAT = 1 AND @IncludeVAT = 1 
     THEN (Price/100) * 80 
     ELSE Price 
     END) AS TotalPrice 
    , C.CategoryId 
    , CategoryName 
FROM Category c 
LEFT JOIN Booking B ON C.CategoryId = B.CategoryId 
WHERE 
    C.IncludeReport = 1 
    and (@HasObservation=0 
     or B.PatientID in 
      (select PatientID 
      from PatientXObservation O 
      where ObservationId IN (1,2,4)) 
     ) 
GROUP BY YEAR(StartTime), MONTH(StartTime), C.CategoryId, CategoryName 
ORDER BY 1, 2, CategoryName 
+0

Это практически заставил меня работает вниз в 1am, чтобы принести свой ноутбук, но вы бьете меня к нему! – Biscuits

0

Вы можете попробовать использовать IF заявление, как в следующем.

CREATE PROCEDURE [dbo].[GetDoctorOperationReportTest] 
    (@IncludeVAT BIT = 0, @HasObservation BIT = 0) 
AS 
BEGIN 
SET NOCOUNT ON 
IF @HasObservation = 1 
    BEGIN 
    SELECT 
     YEAR(StartTime) [Year] 
    , MONTH(StartTime) [Month] 
    , COUNT(BookingId) [BookingCount] 
    , SUM(CASE 
     WHEN IsVAT = 1 AND @IncludeVAT = 1 
     THEN (Price/100) * 80 
     ELSE Price 
     END) AS TotalPrice 
    , C.CategoryId 
    , CategoryName 
    FROM Category c 
    LEFT JOIN Booking B ON C.CategoryId = B.CategoryId 
    LEFT JOIN PatientXObservation O 
      ON B.PatientId = O.PatientId 
     AND O.ObservationId IN (1,2,4) 
    WHERE C.IncludeReport = 1 
    GROUP BY YEAR(StartTime), MONTH(StartTime), C.CategoryId, CategoryName 
    ORDER BY 1, 2, CategoryName 
    END 
ELSE 
    BEGIN 
    SELECT 
     YEAR(StartTime) [Year] 
    , MONTH(StartTime) [Month] 
    , COUNT(BookingId) [BookingCount] 
    , SUM(CASE 
     WHEN IsVAT = 1 AND @IncludeVAT = 1 
     THEN (Price/100) * 80 
     ELSE Price 
     END) AS TotalPrice 
    , C.CategoryId 
    , CategoryName 
    FROM Category c 
    LEFT JOIN Booking B ON C.CategoryId = B.CategoryId 
    WHERE 
    C.IncludeReport = 1 
    GROUP BY YEAR(StartTime), MONTH(StartTime), C.CategoryId, CategoryName 
    ORDER BY 1, 2, CategoryName 
    END 
END 
+0

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

+0

Это просто IF/Else, основанный на операторе BIT @HasObservation; Он использует тот же код, плюс его условие соединения. Не знаете, как это вернет окуней, если только его предоставленный код не вернет дураков для начала? –

0

Вы должны присоединиться:

LEFT JOIN PatientXObservation O 
      ON B.PatientId = O.PatientId 

Затем добавьте предиката

WHERE (@HasObservation = 1 AND O.ObservationId IN (1,2,4)) OR (@HasObservation = 0 AND O.ObservationId < 0) 
+0

Всего строк в настоящее время 7233. После добавления этого условия и левого соединения я получаю 83, если @ HasObservation = 1, что является правильным. 'Но получение 8400 для @ HasObservation = 0 неверно. Я должен получить только 7233' – Developer

+0

Я сделал редактирование. Я предположил, что O.ObservationId никогда не должно быть меньше 0. При условии, что это так, включая предикат для O.ObservationId <0 вместе с @HasObservation = 0, исключает любые записи из таблицы наблюдений и предотвращает добавление дополнительных записей получение. – RelativePHPNewbie

0

Измените свое ГДЕ, чтобы две версии @HasObservation возвращали то, что нужно. Если я понимаю ваш вопрос, то если @HasObservation = 1, то есть еще один фильтр. SQL будет выглядеть следующим образом:

CREATE PROCEDURE [dbo].[GetDoctorOperationReportTest] 
(@IncludeVAT BIT = 0, @HasObservation BIT = 0) 
AS 
BEGIN 
SET NOCOUNT ON  

SELECT 
    YEAR(StartTime) [Year] 
    , MONTH(StartTime) [Month] 
    , COUNT(BookingId) [BookingCount] 
    , SUM(CASE 
     WHEN IsVAT = 1 AND @IncludeVAT = 1 
     THEN (Price/100) * 80 
     ELSE Price 
     END) AS TotalPrice 
    , C.CategoryId 
    , CategoryName 
FROM Category c 
LEFT JOIN Booking B ON C.CategoryId = B.CategoryId 
LEFT JOIN PatientXObservation O 
    ON B.PatientId = O.PatientId 
WHERE 
    C.IncludeReport = 1 
    and 
    (
    (
     @HasObservation = 0   
    ) 
    or 
    (
     @HasObservation = 1 
     and O.ObservationId IN (1,2,4) 
    ) 
) 

GROUP BY YEAR(StartTime), MONTH(StartTime), C.CategoryId, CategoryName 
ORDER BY 1, 2, CategoryName 
END 

Ваш @HasObservation = 0 может при необходимости иметь другой фильтр; вам просто нужно будет отрегулировать код, чтобы включить некоторую логику исключения.

+0

Всего строк в настоящее время 7233. После добавления этого условия и левого соединения я получаю 83, если @ HasObservation = 1, что является правильным. 'Но получение 8400 для @ HasObservation = 0 неверно. Я должен получить только 7233' – Developer

+0

Попробуйте добавить условие к «@HasObservation = 0».Посмотрите на дополнительные строки 1167 и посмотрите, есть ли общая переменная, а затем исключите ее. Например, вы можете исключить, если O.ObservationId имеет значение NULL или что-то еще. ( @HasObservation = 0 и O.ObservationId является NULL ) – Aeroradish