Sql 用于标记 table 中此特定条件至少出现一次或多次的行的语法

Sql Syntax to tag rows in a table where this specific criteria appears at least once or more

我正在使用 SQL Server 2014,并且我有一个 table (t1),其中包含超过 25,000 行的 6 个数字的列表。

t1 的摘录如下:

Id    F1   F2   F3   F4   F5   F6
1     5    11   15   21   30   36
2     8    10   21   25   32   39
3     10   18   23   27   28   32
...

我想编写 2 个案例陈述来执行以下操作:

这是我期望的输出:

Id    F1   F2   F3   F4   F5   F6  LastDigit   CountLastDigit
1     5    11   15   21   30   36    Yes            4
2     8    10   21   25   32   39    No             0
3     10   18   23   27   28   32    Yes            2
...

我一直在写 2 个 case 语句背后的逻辑。任何帮助将不胜感激。

这是一个有趣的问题。您可以使用横向连接来执行此操作。这个想法是将数字列转换为行,按最后一位数字聚合并仅保留出现次数最多的数字。然后你只需要添加一点条件逻辑:

select *
from mytable t
cross apply (
    select top (1) 
        case when count(*) = 1 then 'No' else 'Yes'    end LastDigit,
        case when count(*) = 1 then 0    else count(*) end CountLastDigit
    from (values(f1), (f2), (f3), (f4), (f5), (f6)) x(f)
    group by f % 10
    order by CountLastDigit desc
) z

Demo on DB Fiddle:

Id | F1 | F2 | F3 | F4 | F5 | F6 | LastDigit | CountLastDigit
-: | -: | -: | -: | -: | -: | -: | :-------- | -------------:
 1 |  5 | 11 | 15 | 21 | 30 | 36 | Yes       |              2
 2 |  8 | 10 | 21 | 25 | 32 | 39 | No        |              0
 3 | 10 | 18 | 23 | 27 | 28 | 30 | Yes       |              2

如果要对top ties的计数求和,则子查询中需要多一层聚合:

select *
from mytable t
cross apply (
    select 
        max(LastDigit) LastDigit,
        sum(CountLastDigit) CountLastDigit
    from (
        select top (1) with ties
            case when count(*) = 1 then 'No' else 'Yes'    end LastDigit,
            case when count(*) = 1 then 0    else count(*) end CountLastDigit
        from (values(f1), (f2), (f3), (f4), (f5), (f6)) x(f)
        group by f % 10
        order by CountLastDigit desc
    ) z
) z

横向连接似乎是正确的方法。作为工作的一部分,我会进行汇总:

select t.*, (case when c.num_duplicates > 0 then 'Yes' else 'No' end) as lastDigit,
       coalesce(c.num_duplicates, 0)
from t cross apply
     (select sum(cnt) as num_duplicates
      from (select f % 10 as digit, count(*) as cnt
            from (values (t.f1), (t.f2), (t.f3), (t.f4), (t.f5), (t.f6)) v(f)
            group by f % 10
            having count(*) > 1
           ) c
     ) c;

Here 是一个 db<>fiddle.

尝试以下操作:

;WITH CTE AS
(
    SELECT ID, COL, VAL
    FROM
    (
        SELECT Id, F1%10 F1, F2%10 F2, F3%10 F3, F4%10 F4, F5%10 F5, F6%10 F6
        FROM @TAB
    )T
    UNPIVOT 
    (
        VAL FOR COL IN ( F1, F2, F3, F4, F5, F6 )
    )UPVT
)
, CTE2 AS
(
    SELECT ID, VAL LastDigit, COUNT(DISTINCT COL) VAL_COUNT 
    FROM CTE
    GROUP BY ID, VAL
)
SELECT T.Id, F1, F2, F3, F4, F5, F6
, CASE WHEN VAL_COUNT > 1 THEN 'YES' ELSE 'NO' END LastDigit
, CASE WHEN VAL_COUNT > 1 THEN SUM(VAL_COUNT) ELSE 0 END CountLastDigit 
FROM @tab T
LEFT JOIN CTE2 ON T.Id = CTE2.Id AND VAL_COUNT > 1
GROUP BY T.Id, F1, F2, F3, F4, F5, F6, VAL_COUNT
ORDER BY Id

请找到数据库<>fiddle here.