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 个案例陈述来执行以下操作:
- (1) 标记 6 个数字(F1 到
F6) 作为 "Yes" 至少出现一次或多次,(else "No")
- (2) 给出所有数字的个数(根据上面的条件(1)),
否则给零
这是我期望的输出:
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
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.
我正在使用 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 个案例陈述来执行以下操作:
- (1) 标记 6 个数字(F1 到 F6) 作为 "Yes" 至少出现一次或多次,(else "No")
- (2) 给出所有数字的个数(根据上面的条件(1)), 否则给零
这是我期望的输出:
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
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.