SQL WHERE 子句类似 JOIN 查询

SQL WHERE clause like JOIN query

我有以下程序可以获取每个月的预订数量和总价。

现在我需要传递附加参数 @HasObservation 作为附加参数。过滤的逻辑不仅仅是一个普通的字段过滤器。它必须通过加入其他 table PatientXObservation 来过滤。如果此 table 具有值 1、2、4 的条目,则仅过滤这些预订。

@HasObservation=1 意思是,FETCH 记录满足这个条件

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 table,但查询 运行 非常非常慢。这里的另一个问题是如果@HasObservation 是 0 我需要避免这个过滤器,但不幸的是它选择了 observation=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

您可以尝试使用如下所示的 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

您的加入应该是:

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)

更改您的 WHERE 以获得 @HasObservation 的两个版本 return 所需要的。如果我理解你的问题,那么如果 @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 可以有不同的过滤器;您只需要调整代码以包含一些排他性逻辑。

仅当您的@HasObservation 参数不为零时,您才可以使用 IN 子句进行过滤:

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