还有比我用cte做的更好的代码吗?
我想选择每个id的M和F之间最频繁的值,规则如下:
- 性别值不同于“F”或“M”,在频率计算中未考虑
- 如果最频繁计算不成功=“不确定”
- 如果最频繁计算成功=性别值
下面是一个例子:
资料集
| 身份证|性别|
| --------------|--------------|
| 1|中|
| 1|F|
| 二|中|
| 二|中|
| 二|x|
| 二|F|
| 三|F|
| 三|0|
| 四个|f|
| 四个||
| 五|d的|
预期结果
| 身份证|性别|
| --------------|--------------|
| 1|不确定的|
| 二|中|
| 三|F|
| 四个|F|
我做了什么
WITH cte1 AS (
SELECT
id,
sex,
RANK() OVER (PARTITION BY id ORDER BY count(*)) rn
FROM dataset
WHERE sex ~* '(F|M)' AND sex IS NOT NULL
GROUP BY id, sex
),
cte2 AS (
SELECT id,
max(rn) AS max
FROM cte1
GROUP BY id
),
cte3 AS (
SELECT cte2.id,
sex
FROM cte2
LEFT JOIN cte1 ON cte2.id=cte1.id AND max=rn
WHERE cte1.id IS NOT NULL
),
cte4 AS (
SELECT id,
count(*) as cnt
FROM cte3
GROUP BY id
)
SELECT DISTINCT cte4.id,
CASE
WHEN cnt>1 THEN 'inconclusive'
WHEN cnt=1 AND SEX IN ('F', 'M') THEN sex
END AS sex
FROM cte4
LEFT JOIN cte3 ON cte4.id=cte3.id
对我来说,代码在某种意义上是有效的,它给出了适当的结果,但它看起来有点笨重,我正在寻找改进。有吗?
注意:我使用了DISTINCT ON ()
,但它不能检索id 1 = inconclusive(F或M取决于顺序)
1条答案
按热度按时间xqkwcwgp1#
你似乎把事情复杂化了。
首先,我会过滤掉M或F以外的值,然后按
id
聚合,并计算每个值出现的次数:我不认为
where
子句中需要正则表达式匹配,因为似乎您只想保留'F'
和'M'
值。从那时起,我们要做的就是比较计数。我们可以在外部查询中执行,这样我们就不需要重复条件表达式: