【问题标题】:SQL Server : SELECT ID having only a single conditionSQL Server:SELECT ID 只有一个条件
【发布时间】:2018-01-08 17:43:29
【问题描述】:

我有一个患者表,其中包含患者的病情等详细信息。从下表中,我想选择患者,索赔只有一个条件 - “高血压”。示例患者 B 是预期输出。患者 A 不会被选中,因为他声称患有多种疾病。

+----+---------+--------------+
| ID | ClaimID |  Condition   |
+----+---------+--------------+
| A  |   14234 | Hypertension |
| A  |   14234 | Diabetes     |
| A  |   63947 | Diabetes     |
| B  |   23853 | Hypertension |
+----+---------+--------------+

我尝试使用如下 NOT IN 条件,但似乎没有帮助

SELECT ID, ClaimID, Condition 
FROM myTable 
WHERE Condition IN ('Hypertension') 
  AND Condition NOT IN ('Diabetes') 

【问题讨论】:

    标签: sql sql-server notin


    【解决方案1】:

    一种方法使用not exists

    select t.*
    from mytable t
    where t.condition = 'Hypertension' and
          not exists (select 1
                      from mytable t2
                      where t2.id = t.id and t2.condition <> t.condition
                     );
    

    【讨论】:

    • 如果大数据集子查询可能会出现性能问题。
    • @AmitVerma 。 . .如果性能是一个问题,您只需添加适当的索引。
    【解决方案2】:

    或者你可以这样做:

    select 
        id,
        claim_id,
        condition
    from 
        patient
    where 
        id in
        (
            select
                id
            from
                patient
            group by
                id having count (distinct condition) = 1
        );
    

    结果:

    id claim_id    condition
    -- ----------- ----------------
    B        23853 Hypertension
    
    (1 rows affected)
    

    设置:

    create table patient
    (
        id         varchar(1),
        claim_id   int,
        condition  varchar(16)
    );
    
    insert into patient (id, claim_id, condition) values ('A', 14234, 'Hypertension');
    insert into patient (id, claim_id, condition) values ('A', 14234, 'Diabetes');
    insert into patient (id, claim_id, condition) values ('A', 63947, 'Diabetes');
    insert into patient (id, claim_id, condition) values ('B', 23853, 'Hypertension');
    

    【讨论】:

      【解决方案3】:

      您可以通过 CTE 做到这一点。

      我使用两个参数设置此 CTE,一个是您寻求的条件,另一个是要查找的最大组合条件数(在您的情况下为 1)。

      DECLARE @myTable TABLE (Id VARCHAR(1), ClaimID INT, Condition VARCHAR(100))
      INSERT INTO @myTable (Id, ClaimID, Condition)
      SELECT 'A',14234,'Hypertension' UNION ALL
      SELECT 'A',14234,'Diabetes' UNION ALL
      SELECT 'A',63947,'Diabetes' UNION ALL
      SELECT 'B',23853,'Hypertension'
      
      DECLARE @Condition VARCHAR(100)
      DECLARE @MaxConditions TINYINT
      
      SET @Condition='Hypertension'
      SET @MaxConditions=1
      
      ; WITH CTE AS
      (
          SELECT *, COUNT(2) OVER(PARTITION BY ClaimID) AS CN
          FROM @myTable T1
          WHERE EXISTS (SELECT 1 FROM @myTable T2 WHERE T1.ClaimID=T2.ClaimID AND T2.Condition=@Condition)
      )
      
      SELECT *
      FROM CTE
      WHERE CN<=@MaxConditions
      

      如果您不关心绒毛,并且只希望所有 ClaimID 都具有一个条件,而不管它是哪种条件,请使用它。

      DECLARE @myTable TABLE (Id VARCHAR(1), ClaimID INT, Condition VARCHAR(100))
      INSERT INTO @myTable (Id, ClaimID, Condition)
      SELECT 'A',14234,'Hypertension' UNION ALL
      SELECT 'A',14234,'Diabetes' UNION ALL
      SELECT 'A',63947,'Diabetes' UNION ALL
      SELECT 'B',23853,'Hypertension'
      
      DECLARE @MaxConditions TINYINT
      
      SET @MaxConditions=1
      
      ; WITH CTE AS
      (
          SELECT *, COUNT(2) OVER(PARTITION BY ClaimID) AS CN
          FROM @myTable T1
      )
      
      SELECT *
      FROM CTE
      WHERE CN<=@MaxConditions
      

      【讨论】:

        【解决方案4】:

        这是使用Having 子句的一种方法

        SELECT t.*
        FROM   mytable t
        WHERE  EXISTS (SELECT 1
                       FROM   mytable t2
                       WHERE  t2.id = t.id
                       HAVING Count(CASE WHEN condition = 'Hypertension' THEN 1 END) > 0
                              AND Count(CASE WHEN condition != 'Hypertension' THEN 1 END) = 0) 
        

        【讨论】:

        • 建议将最后一个案例更改为!= hypertension,以便它可以处理其他继发性疾病而不仅仅是糖尿病。
        【解决方案5】:

        还有其他几种方法可以做到这一点:

            declare @TableA  table(Id char,
                                   ClaimId int,
                                   Condition varchar(250));
            insert into @TableA (id, claimid, condition)
                        values ('A', 14234, 'Hypertension'),
                               ('A', 14234, 'Diabetes'),
                               ('A', 63947, 'Diabetes'),
                               ('B', 23853, 'Hypertension')       
        
        
            select id, claimid, condition
            from @TableA a
            where not exists(select id
                             from @TableA b
                             where a.id = b.id
                             group by b.id
                             having count(b.id) > 1)
        
            OR
        
            ;with cte as
           (
             select id, claimid, condition
             from @TableA
           )
           ,
           cte2 as
           (
             Select id, count(Id) as counts
             from cte
             group by id
             having count(id) < 2       
            )
        
           Select cte.id, claimid, condition
           From cte
           inner join
           cte2
           on cte.id = cte2.id
        

        【讨论】:

          【解决方案6】:

          我决定将我的答案修改为一个合适的答案。

          您的问题的一个简单解决方案是计算行数而不是 ID 值(因为它不是整数)。

          这里简单介绍一下:

          SELECT 
              ID 
          FROM 
              #PatientTable 
          GROUP BY 
              ID 
          HAVING
              ID = ID AND COUNT(*) = 1 
          

          这将返回 ID B

          +----+
          | ID |
          +----+
          | B  |
          +----+
          

          当然,这还不够,因为您可能需要处理大量数据并需要更多过滤。

          所以,我们将把它用作子查询。

          将其用作子查询很简单:

          SELECT
              ID, 
              ClaimID, 
              Condition
          FROM 
              #PatientTable
          WHERE 
              ID = (SELECT ID AS NumberOfClaims FROM #PatientTable GROUP BY ID HAVING ID = ID AND COUNT(*) = 1)
          

          这将返回

          +----+---------+--------------+
          | ID | ClaimID |  Condition   |
          +----+---------+--------------+
          | B  |   23853 | Hypertension |
          +----+---------+--------------+
          

          到目前为止一切顺利,但我们可能会面临另一个问题。假设您有来自多名患者的多项索赔,按原样使用此查询只会显示一名患者。为了显示所有患者,我们需要在 WHERE 子句下使用 IN 而不是 =

          WHERE 
              ID IN (SELECT ID AS NumberOfClaims FROM #PatientTable GROUP BY ID HAVING ID = ID AND COUNT(*) = 1)
          

          这将列出所有属于这种情况的患者。

          如果您需要更多条件进行过滤,只需将它们添加到 WHERE 子句中即可。

          【讨论】:

          【解决方案7】:
          SELECT id, sum(ct)
          FROM (SELECT customer_id, CASE WHEN category = 'X' THEN 0 else 1 
          end ct
          FROM MASTER_TABLE
          ) AS t1
          GROUP BY id
          HAVING sum(ct) = 0
          

          sum(ct) 大于 1 的 id 将有多个条件

          【讨论】:

            【解决方案8】:

            使用联接而不是子查询。联接的性能总是更好。您可以使用以下查询。

            SELECT T1.id, T1.claimid, T1.Condition
            FROM mytable T1
            INNER JOIN 
            (
                select id, count(Condition)  counter
                from mytable 
                group by id HAVING COUNT(DISTINCT CONDITION)=1
            ) T2 ON T1.ID=T2.ID
            WHERE  T2.counter=1
            

            【讨论】:

              猜你喜欢
              • 2014-11-07
              • 1970-01-01
              • 1970-01-01
              • 2021-02-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-03-06
              相关资源
              最近更新 更多