按基于类别的多列值返回不同的记录

oba*_*sta 1 sql-server sql-server-2014

ID    MODEL    MODELSTATUS    CONTROL
11     100      GOOD           XN
24     100      TRENDING       BF
33     101      GOOD           XN
46     102      BAD            BF
50     103      BAD            XN
64     103      BAD            BF
77     104      PENDING        XN
89     104      TRENDING       BF
92     105      TRENDING       BF
93     105      TRENDING       XN
Run Code Online (Sandbox Code Playgroud)

鉴于上面的数据,我将如何返回下面的结果。可以有 1 条或 2 条(最多)具有相同 MODEL 的记录。如果 MODEL 有 2 个记录,则 CONTROL 将不同。

如果 MODESTATUS 为“趋势”,则返回该记录。否则,如果 MODELSTATUS 是 'Pending' 或 'Bad' 返回该记录。否则,如果 MODEL 有 2 条记录,其中 MODELSTATUS 与 CONTROL 的返回记录相同,则为“XN”

ID    MODEL    MODELSTATUS    CONTROL
24    100      TRENDING       BF
33    101      GOOD           XN
46    102      BAD            BF
50    103      BAD            XN
77    104      PENDING        BF
93    105      TRENDING       XN
Run Code Online (Sandbox Code Playgroud)

Jul*_*eur 5

此查询提供所需的输出:

WITH data AS(
    SELECT [ID], [MODEL], [MODELSTATUS], [CONTROL]
        , r = ROW_NUMBER() OVER(PARTITION BY [MODEL] ORDER BY
            CASE WHEN MODELSTATUS = 'TRENDING' THEN 1 ELSE 0 END DESC
            , CASE WHEN MODELSTATUS IN ('PENDING', 'BAD') THEN 1 ELSE 0 END DESC
            , CASE WHEN [CONTROL] = 'XN' THEN 1 ELSE 0 END DESC
            , [ID] DESC
        )
    FROM @Table1
)
SELECT [ID], [MODEL], [MODELSTATUS], [CONTROL]
FROM data
WHERE r = 1;
Run Code Online (Sandbox Code Playgroud)

请参阅此SQL 小提琴

我假设这只是一个具有易于理解的 char 值的示例表,并且实际数据使用 int 而不是 varchar 进行状态和控制。

就现实生活中的性能和IO而言,如果这种类型的表变大了,明智的做法是改进设计,将每个Control和Status的varchar替换为tinyint id。

输出

ID  MODEL   MODELSTATUS CONTROL
24  100     TRENDING    BF
33  101     GOOD        XN
46  102     BAD         BF
50  103     BAD         XN
89  104     TRENDING    BF
93  105     TRENDING    XN
Run Code Online (Sandbox Code Playgroud)