查询以显示不同的组合,然后显示每个不同组合的计数

Posted

技术标签:

【中文标题】查询以显示不同的组合,然后显示每个不同组合的计数【英文标题】:Query to display distinct combination and then display count for each distinct combination 【发布时间】:2021-01-07 04:47:14 【问题描述】:

有一个 transid 字段,此表中将存在多行,其中包含配置值列表。对于所有的 transid,我想按计数检索表组中存在的所有不同的 transid、config_name 和 value 字段组合

我的连接查询没有按预期返回结果。下面是表结构、使用的查询、结果和预期结果

表格

transid            config_name               value
1                   payment_fee                instant
2                   eligible_account           true
1                   Block_intl_trans           false
5                   payment_fee                provider_charge
1                   eligible_account           false  
1                         KycEligible               0
2                         KycEligible               1
5                        KycEligible                1
5                   Block_intl_trans            true
2                   Block_intl_trans            false   
2                   payment_fee                 provider_charge
5                   eligible_account            true 

上面的表格结构意味着下面是每个用户的配置值的组合。

transid  KycEligible  payment_fee     eligible_account     Block_intl_trans
1      0            instant          false                false
2      1            provider_charge  true                 false
5      1            provider_charge  true                 false       

                   

下面是我用来将行转换为列然后按 config_name 对它们进行分组的查询(对于每个 config_name,而不是每个配置键和值组合的多行)。然后选择表中存在的 KycEligible、configname 和 value 组合的所有不同组合以及每个不同组合的计数。

select
    distinct
    max(case when b.config_name = 'KycEligible' then b.config_value end) KycEligible,
    max(case when b.config_name = 'payment_fee' then b.config_value end)  payment_fee,
    max(case when b.config_name = 'eligible_account' then b.config_value end)  eligible_account,
    max(case when b.config_name = 'Block_intl_trans' then b.config_value end)  Block_intl_trans,
    count(*) AS COUNT
from tableA b
where b.config_name in ('KycEligible', 'payment_fee', 'eligible_account', 'Block_intl_trans')
group by b.config_name
having count(*) > 1

预期结果:

KycEligible  payment_fee     eligible_account     Block_intl_trans  Count
    0            instant          false                false             1
    1            provider_charge  true                 false             2 

我的查询没有返回预期的结果。有人可以帮忙解决这个问题吗?

【问题讨论】:

请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出尽可能少的代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。 How to Ask 暂停总体目标的工作,将代码砍到第一个表达式,没有给出你期望的内容,说出你期望的内容和原因。 1) 您在文本和源数据示例中的列名不同,因此您的解释不清楚。同步。 2)您在代码中使用了错误的非标准引号字符。正确的。 3) 您在name 列中检查“instant”和“provider_charge”,而这些值在value 列中。 4) 预期结果在 Block_intl_trans=false 的情况下连续显示 Count=2,但 transid=5 的 Block_intl_trans 为 true。 附言。 fiddle Block_intl_trans for transid=5 是 false 还是 true? 考虑处理应用代码中数据显示的问题 【参考方案1】:

我认为你需要这样的东西:

SELECT
  KycEligible, payment_fee, eligible_account, Block_intl_trans, COUNT(*) CNT
FROM (
  SELECT
    (SELECT MAX(t0.config_value) FROM test t0 WHERE t0.config_name = 'KycEligible' AND t0.transid = t.transid) as KycEligible,
    (SELECT MAX(t0.config_value) FROM test t0 WHERE t0.config_name = 'payment_fee' AND t0.transid = t.transid) as payment_fee,
    (SELECT MAX(t0.config_value) FROM test t0 WHERE t0.config_name = 'eligible_account' AND t0.transid = t.transid) as eligible_account,
    (SELECT MAX(t0.config_value) FROM test t0 WHERE t0.config_name = 'Block_intl_trans' AND t0.transid = t.transid) as Block_intl_trans
  FROM
    test t
  GROUP BY t.transid
) dt
GROUP BY KycEligible, payment_fee, eligible_account, Block_intl_trans
;

这将给出以下内容:

ycEligible  payment_fee         eligible_account    Block_intl_trans    CNT
0           instant○            false               false                   1
1           provider_charge     true                false                   1
1           provider_charge     true                true                    1

结果与预期的问题不同:

2 and 5 transids have different Block_intl_trans
1 and 5 transids have different payment_fee
1 and 2 transids have different eligible_account

【讨论】:

我没有投反对票,而是尝试在评论中 Akina 给出的小提琴上运行您的查询。你会发现计数是错误的。【参考方案2】:

我给出两个小提琴示例,因为您提供的示例数据不一致。

    此小提琴适用于 transid=5 且 Block_intl_trans 数据为 true - 与您的表数据示例一致:https://www.db-fiddle.com/f/r1imsYP8dQxkLSo5SkYcVK/3 此小提琴适用于 transid=5 且 Block_intl_trans 数据为 false - 与您说明的配置组合一致:https://www.db-fiddle.com/f/r1imsYP8dQxkLSo5SkYcVK/4

我猜唯一的组合将来自所有config_name 值。这是示例查询:

SELECT KycEligible, payment_fee, eligible_account, Block_intl_trans, COUNT(*) FROM
(SELECT transid,
       GROUP_CONCAT(CASE WHEN config_name="KycEligible" THEN config_value END) AS "KycEligible",
       GROUP_CONCAT(CASE WHEN config_name="payment_fee" THEN config_value END) AS "payment_fee",
       GROUP_CONCAT(CASE WHEN config_name="eligible_account" THEN config_value END) AS "eligible_account",
       GROUP_CONCAT(CASE WHEN config_name="Block_intl_trans" THEN config_value END) AS "Block_intl_trans"
 FROM TableA
 GROUP BY transid) V
GROUP BY KycEligible, payment_fee, eligible_account, Block_intl_trans;

【讨论】:

【参考方案3】:

使用 Max 进行简单查询, 结果计数可以基于您的输入数据(transid=5、config=Block_intl_trans、value=false 或 value=true)

SELECT KycEligible, payment_fee, eligible_account, Block_intl_trans, COUNT(*) FROM
( 
SELECT 
       transid,
       max(CASE WHEN config_name="KycEligible" THEN value END) AS "KycEligible",
       max(CASE WHEN config_name="payment_fee" THEN value END) AS "payment_fee",
       max(CASE WHEN config_name="eligible_account" THEN value END) AS "eligible_account",
       max(CASE WHEN config_name="Block_intl_trans" THEN value END) AS "Block_intl_trans"
 FROM <YOUR_TABLE_NAME>
 GROUP BY transid
 ) tmp
GROUP BY KycEligible, payment_fee, eligible_account, Block_intl_trans;

【讨论】:

以上是关于查询以显示不同的组合,然后显示每个不同组合的计数的主要内容,如果未能解决你的问题,请参考以下文章

如何在一个 SQL Server 查询中组合不同的计数

SQL聚合中同一列内的多个值的不同计数

Google BigQuery:如何查询两个不同值之间的共享值计数?

如何组合 2 个 SQL 查询并检索累积计数?

具有不同元素组合的自动布局

将一个sql语句用于不同的搜索组合