【问题标题】:Simplify TSQL by Getting Ids that matched or first in the row number if not matched通过获取匹配的 Id 来简化 TSQL,如果不匹配,则在行号中排在第一位
【发布时间】:2021-12-02 12:36:58
【问题描述】:

我有这个示例,其中 Id1 作为组,Id2 是组中唯一的 Id。

如果Id2和Id1一样,我想把它的行作为整个组的代表。

如果没有与Id2匹配的Id1,那么我想根据Id2的升序获取第一行。

我就是这样做的,但我只是想知道如何简化 tsql:

WITH cte AS
(
    SELECT 'A' AS Id1, '1' AS Id2, 'DSFSF' AS _detail
    UNION ALL
    SELECT 'A' AS Id1, '2' AS Id2, 'ASDF' AS _detail
    UNION ALL
    SELECT 'A' AS Id1, 'A' AS Id2, '434242' AS _detail
    UNION ALL
    SELECT 'B' AS Id1, '1' AS Id2, 'gsreew' AS _detail
    UNION ALL
    SELECT 'B' AS Id1, '2' AS Id2, 'werw' AS _detail
    UNION ALL
    SELECT 'B' AS Id1, '3' AS Id2, '67575' AS _detail
),
cte2 AS
(
    SELECT 
        *, 
        ROW_NUMBER() OVER (PARTITION BY Id1 ORDER BY Id2) AS rn,
        CASE 
            WHEN Id1 = Id2 THEN 1 ELSE 0 
        END AS _matchedid
    FROM
        cte
),
cte3 AS
(
    SELECT
        Id1, SUM(_matchedid) AS _matched
    FROM
        cte2
    GROUP BY
        Id1
)
SELECT *
FROM cte2 a
INNER JOIN cte3 b ON a.Id1 = b.Id1
WHERE b._matched = 1 AND a.Id1 = a.Id2

UNION ALL

SELECT *
FROM cte2 a
INNER JOIN cte3 b ON a.Id1 = b.Id1
WHERE b._matched = 0 AND a.rn = 1

【问题讨论】:

    标签: sql-server tsql


    【解决方案1】:

    您可以为此使用条件行编号解决方案

    WITH cte AS
    (
        SELECT 'A' AS Id1, '1' AS Id2, 'DSFSF' AS _detail
        UNION ALL
        SELECT 'A' AS Id1, '2' AS Id2, 'ASDF' AS _detail
        UNION ALL
        SELECT 'A' AS Id1, 'A' AS Id2, '434242' AS _detail
        UNION ALL
        SELECT 'B' AS Id1, '1' AS Id2, 'gsreew' AS _detail
        UNION ALL
        SELECT 'B' AS Id1, '2' AS Id2, 'werw' AS _detail
        UNION ALL
        SELECT 'B' AS Id1, '3' AS Id2, '67575' AS _detail
    ),
    cteWithRn AS
    (
        SELECT *
          ROW_NUMBER() OVER (PARTITION BY Id1, CASE WHEN Id1 = Id2 THEN 0 ELSE 1 END, Id2) AS rn
        FROM cte
    )
    SELECT *
    FROM cteWithRn
    WHERE rn = 1;
    

    【讨论】:

      【解决方案2】:

      一个想法使用TOP (1) WITH TIESROW_NUMBER 与条件ORDER BY

      SELECT TOP (1) WITH TIES *
      FROM CTE
      ORDER BY ROW_NUMBER() OVER (PARTITION BY ID1 ORDER BY CASE ID1 WHEN ID2 THEN NULL ELSE ID2 END);
      

      请注意,由于您的列ID2varchar,因此'10' 之类的值将比'2' 之类的值

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-06-30
        • 2016-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-01
        • 2021-04-29
        相关资源
        最近更新 更多