匹配并合并多个缩写可能性

huangapple go评论59阅读模式
英文:

Match and coalesce multiple abbreviated possibilities

问题

SELECT ProjectID,
       CONCAT_WS(', ', 
         CASE WHEN CHARINDEX('00', SpecialConditions) > 0 THEN 'No Fruits' ELSE NULL END,
         CASE WHEN CHARINDEX('CB', SpecialConditions) > 0 THEN 'Cranberry' ELSE NULL END,
         CASE WHEN CHARINDEX('K', SpecialConditions) > 0 THEN 'Kiwi' ELSE NULL END,
         CASE WHEN CHARINDEX('SP', SpecialConditions) > 0 THEN 'Sugar Plum' ELSE NULL END,
         CASE WHEN CHARINDEX('WM', SpecialConditions) > 0 THEN 'Watermelon' ELSE NULL END
       ) AS SpecialConditions
FROM Projects;
英文:

I have a table of project ID data and another of abbreviated circumstances related to the project. I would like to have the query output all the abbreviated options in a coalesced and descriptive format.

ProjectID is int
SpecialConditions is varchar

Query:

| ProjectID | SpecialConditions |
| --------  | ----------------- |
| 2023-0001 |        00         |
| 2023-0002 |        CBSP       |
| 2023-0003 |        KCB        |
| 2023-0004 |                   |
| 2023-0005 |        K          |
| 2023-0006 |        WMCBSP     |

List of abbreviated details:

00 = No Fruits
CB = Cranberry
K  = Kiwi
SP = Sugar Plum
WM = Watermelon

Desired output:

| ProjectID | SpecialConditions                 |
| --------  | --------------------------------- |
| 2023-0001 | No Fruits                         |
| 2023-0002 | Cranberry, Sugar Plum             |
| 2023-0003 | Kiwi, Cranberry                   |
| 2023-0004 |                                   |
| 2023-0005 | Kiwi                              |
| 2023-0006 | Watermelon, Cranberry, Sugar Plum |

Previously I was using CASE, then I started realizing multiple conditions exist in different order which requires me to rewrite the query.

SELECT CASE When SpecialConditions = '00' then 'No Fruits'
When SpecialConditions = 'CB' then 'Cranberry'
When SpecialConditions = 'K' then 'Kiwi'
When SpecialConditions = 'SP' then 'Sugar Plum'
When SpecialConditions = 'WM' then 'Watermelon'
When SpecialConditions = 'SPWM' then 'Sugar Plum, Watermelon'
When SpecialConditions = 'WMSP' then 'Sugar Plum, Watermelon'
else (coalesce(SpecialConditions, '') END as 'Fruits'`
From Projects

Looking for any feedback on how I can write this query

答案1

得分: 3

如果您定义并填充了一个查找表,将代码映射到描述,您可以使用LIKE运算符或CHARINDEX()函数匹配查找表条目。然后可以使用STRING_AGG()函数来组合结果。

SELECT P.ProjectID, P.SpecialConditions, A.Fruits
FROM Projects P
CROSS APPLY (
    SELECT COALESCE(
        STRING_AGG(FL.Description, ', ') WITHIN GROUP(ORDER BY M.MatchPos)
        , P.SpecialConditions
        , '') AS Fruits
    FROM FruitLookup FL
    CROSS APPLY (SELECT CHARINDEX(FL.Code, P.SpecialConditions) AS MatchPos) M
    WHERE M.MatchPos > 0
) A

对于SQL Server 2016及更早版本,可以在STRING_AGG()函数的位置使用旧的FOR XML技巧。

SELECT P.ProjectID, P.SpecialConditions, A.Fruits
FROM Projects P
CROSS APPLY (
    SELECT COALESCE(
        STUFF((
            SELECT ', ' + FL.Description
            FROM FruitLookup FL
            CROSS APPLY (SELECT CHARINDEX(FL.Code, P.SpecialConditions) AS MatchPos) M
            WHERE M.MatchPos > 0
            ORDER BY M.MatchPos
            FOR XML PATH(''), TYPE
        ).value('.', 'varchar(max)'), 1, 2, '')
        , P.SpecialConditions
        , '') AS Fruits
) A

上述代码将按照它们在原始字符串中出现的顺序(在上述代码中的MatchPos)对映射的名称进行排序。

请注意,匹配逻辑不能防止由包含字符序列的相邻代码引起的意外匹配。您需要想出一种处理这些情况的策略。

示例结果:

ProjectID SpecialConditions Fruits
2023-0001 00 No Fruits
2023-0002 CBSP Cranberry, Sugar Plum
2023-0003 KCB Kiwi, Cranberry
2023-0004
2023-0005 K Kiwi
2023-0006 WMCBSP Watermelon, Cranberry, Sugar Plum
2023-0007 SPCBWM Sugar Plum, Cranberry, Watermelon

参见 这个 db<>fiddle,其中包含上述代码的工作示例。

英文:

If you define and populate a lookup table that maps codes to descriptions, you can match lookup table entries using a LIKE operator or CHARINDEX() function. The STRING_AGG() function can then be used to combine the results.

SELECT P.ProjectID, P.SpecialConditions, A.Fruits
FROM Projects P
CROSS APPLY (
    SELECT COALESCE(
        STRING_AGG(FL.Description, &#39;, &#39;) WITHIN GROUP(ORDER BY M.MatchPos)
        , P.SpecialConditions
        , &#39;&#39;) AS Fruits
    FROM FruitLookup FL
    CROSS APPLY (SELECT CHARINDEX(FL.Code, P.SpecialConditions) AS MatchPos) M
    WHERE M.MatchPos &gt; 0
) A

For SQL Server 2016 and earlier, the old FOR XML hack can be used in place of the STRING_AGG() function.

SELECT P.ProjectID, P.SpecialConditions, A.Fruits
FROM Projects P
CROSS APPLY (
    SELECT COALESCE(
        STUFF((
            SELECT &#39;, &#39; + FL.Description
            FROM FruitLookup FL
            CROSS APPLY (SELECT CHARINDEX(FL.Code, P.SpecialConditions) AS MatchPos) M
            WHERE M.MatchPos &gt; 0
            ORDER BY M.MatchPos
            FOR XML PATH(&#39;&#39;), TYPE
        ).value(&#39;.&#39;, &#39;varchar(max)&#39;), 1, 2, &#39;&#39;)
        , P.SpecialConditions
        , &#39;&#39;) AS Fruits
) A

The above will order the mapped names in the same order as they appear in the original string (MatchPos in the above code).

Note that the matching logic does not protect against accidental matches caused by adjacent codes that contain character sequences that happen to match other codes. You will need to figure out a strategy to handle those cases.

Sample results:

ProjectID SpecialConditions Fruits
2023-0001 00 No Fruits
2023-0002 CBSP Cranberry, Sugar Plum
2023-0003 KCB Kiwi, Cranberry
2023-0004
2023-0005 K Kiwi
2023-0006 WMCBSP Watermelon, Cranberry, Sugar Plum
2023-0007 SPCBWM Sugar Plum, Cranberry, Watermelon

See this db<>fiddle for a working example that includes both versions of the above code.

huangapple
  • 本文由 发表于 2023年6月2日 02:05:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76384573.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定