【问题标题】:SQL case statement - 3 clauses?SQL case 语句 - 3 个子句?
【发布时间】:2018-07-04 12:17:49
【问题描述】:

希望有人可以帮助解决这个问题

我有一张如下所示的表格

ID | Name | Age | GroupID | Services
33 | Pam  | 34  |  334    |   3
33 | Pam  | 34  |  334    |   4
43 | Lily | 56  |  10     |   3
67 | Bob  | 22  |  11     |   4

注意 Pam 有 2 行,因为她有 2 种不同类型的服务。

我将如何编写一个案例陈述来表明姓名列中的人是否拥有服务 3、服务 4 或两者兼有。

例如,我在查询上述内容时的输出是

 ID | Name | Age | GroupID | Services | SG
    33 | Pam  | 34  |  334    |   3   | 3 & 4
    33 | Pam  | 34  |  334    |   4   | 3 & 4
    43 | Lily | 56  |  10     |   3   | 3 Only
    67 | Bob  | 22  |  11     |   4   | 4 Only

一如既往的感谢大家

【问题讨论】:

  • 我们可以假设某人属于 3,那么返回应该是 3、4 和 5?这意味着您需要引入一种方法来(请原谅编造的词)“语法化”返回的数据集。这并不是 SQL Server 的真正强项。

标签: sql sql-server tsql string-concatenation


【解决方案1】:

这样的?

编辑:添加DISTINCT 以避免3 & 4 & 4 的情况

DECLARE @mockupTable TABLE(ID INT,Name VARCHAR(100),Age INT, GroupID INT,[Services] INT);
INSERT INTO @mockupTable VALUES
  (33,'Pam',34,334,3)
 ,(33,'Pam',34,334,4)
 ,(43,'Lily',56,10,3)
 ,(67,'Bob',22,11,4);

 SELECT t.*
       ,STUFF((
            SELECT DISTINCT ' & ' + CAST(x.[Services] AS VARCHAR(10))
            FROM @mockupTable AS x
            WHERE t.ID=x.ID 
            ORDER BY x.[Services]
            FOR XML PATH(''),TYPE
        ).value('.','nvarchar(max)'),1,3,'') AS SG
 FROM @mockupTable AS t;

结果

+----+------+-----+---------+----------+--------------------+
| ID | Name | Age | GroupID | Services | SG                 |
+----+------+-----+---------+----------+--------------------+
| 33 | Pam  | 34  | 334     | 3        | 3 & 4              |
+----+------+-----+---------+----------+--------------------+
| 33 | Pam  | 34  | 334     | 4        | 3 & 4              |
+----+------+-----+---------+----------+--------------------+
| 43 | Lily | 56  | 10      | 3        | 3                  |
+----+------+-----+---------+----------+--------------------+
| 67 | Bob  | 22  | 11      | 4        | 4                  |
+----+------+-----+---------+----------+--------------------+

如果要添加 only,这是查询:

SELECT t.*
        ,STUFF((
            SELECT DISTINCT ' & ' + CAST(x.[Services] AS VARCHAR(10))
            FROM @mockupTable AS x
            WHERE t.ID=x.ID 
            ORDER BY x.[Services]
            FOR XML PATH(''),TYPE
        ).value('.','nvarchar(max)'),1,3,'') 
        + CASE WHEN COUNT(*) OVER(PARTITION BY ID) = 1 THEN ' Only' ELSE '' END AS SG
    FROM @mockupTable AS t;

【讨论】:

  • 我不相信 distinct 是个好主意。如果多次使用相同的服务,这可能应该反映在输出中。但希望 id 和 services 的组合有一个独特的约束。
【解决方案2】:

试试这个

SELECT
    *,
    SG = CASE Q.Cnt
        WHEN 1 THEN '3 & 4' 
       ELSE CAST(T1.[Services] AS VARCHAR(10))+' Only' END
    FROM YourTable T1
       OUTER APPLY
       (
          SELECT
             Cnt = COUNT(DISTINCT Srv)
             FROM YourTable T2
                WHERE t2.Id = t1.Id
                    AND t2.[Services]  IN (3,4)
                    AND t2.[Services] <> t1.[Services]
       )Q

【讨论】:

  • 在这种情况下,他只需要 3&4,这是我能想到的最简单的方法
  • 嗯,但很明显,这应该是工作负载所承载的实际值......
【解决方案3】:

如果你真的只有两个服务 3 和 4 并且永远不会发生同一个人有两次相同的服务,那么我会使用

select *, case when (count(*) over (partition by name)) = 2 then '3 & 4' 
          else cast(services as varchar) + ' Only' end
from t

dbfiddle demo

【讨论】:

  • 如果您有 2 个相同人员和相同服务的条目,这将不会返回预期结果。假设我有两次 Id 1 和 Service 3 的条目并且没有 Service 4,它仍然会说 3&4
  • @JayasuryaSatheesh 是的,我已经更新了答案。谢谢。
【解决方案4】:

请试试这个---

注意-使用 CHARINDEX 在末尾添加“仅”文本。

;WITH CTE1 AS 
(
    select 33 id , 'Pam' Name , 34 Age ,  334 GroupBy   ,   3 Services
    union all
    select 33 , 'Pam'  , 34  ,  334    ,   4
    union all
    select 43 , 'Lily' , 56  ,  10     ,   3
    union all
    select 67 , 'Bob'  , 22  ,  11     ,   4
)
,CTE2 AS
(
    SELECT * ,
                  STUFF 
                    ((
                        SELECT CONCAT(' & ' , Services ) Services
                        FROM CTE1 a
                        WHERE ( a.id = b.id )
                        FOR XML PATH(''),Type
                    ).value('.','VARCHAR(MAX)') ,1,2,'') 
                    AS SG
    FROM CTE1 b
)
SELECT Id,Name,Age,GroupBy,Services , CASE WHEN CHARINDEX('&',SG,0) = 0 THEN CONCAT(SG,' Only') ELSE SG END SG 
FROM CTE2

输出

Id          Name Age         GroupBy     Services    SG
----------- ---- ----------- ----------- ----------- -------------------
33          Pam  34          334         3            3 & 4
33          Pam  34          334         4            3 & 4
43          Lily 56          10          3            3 Only
67          Bob  22          11          4            4 Only

(4 rows affected)

【讨论】:

    【解决方案5】:

    如果您使用的是 MS SQL2017,这个应该可以解决问题:

    WITH A AS
    (
        SELECT
                ID, Name, Age, GroupID,
                STRING_AGG (Services, ' & ')
        FROM yourtable 
        GROUP BY ID, Name, Age, GroupID
    )
    SELECT DISTINCT
            A.ID, A.Name, A.Age, B.Services,
            CASE 
             WHEN LEN(A.SG) = 1 THEN A.SG + ' Only'
             ELSE A.SG
            END AS SG
    FROM yourtable AS B
    LEFT JOIN A
        ON A.ID = B.ID
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-26
      • 1970-01-01
      • 2014-12-31
      • 2012-05-25
      • 2021-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多