MySQL在1个表中选择不同的记录并根据另一个表中的值计算每个组

Posted

技术标签:

【中文标题】MySQL在1个表中选择不同的记录并根据另一个表中的值计算每个组【英文标题】:MySQL select Distinct records in 1 table and count each group based on values in another table 【发布时间】:2014-01-20 20:22:42 【问题描述】:

表 1:

| user           | bid |
---------------------------
|    may    |      0.06      |
|    dee    |      0.05      |
|    jay    |      0.04      |
|    mac    |      0.03      |
|    dee    |      0.02      |
|    mac    |      0.01      |

表 2:

| user          | ratio|
---------------------------
|    dee    |      .25      |
|    jay    |      .45      |
|    mac    |      .85      |
|    fil    |      .75      |
|    may    |      .95      |

我想根据表 2 中的配给计算表 1 中有多少不同的用户落在特定范围 (0-.99) 内。

输出:

| Ratio_Group     | Count|
---------------------------
|    0.00-0.25 |      1     |
|    0.25-0.50 |      1     |
|    0.50-0.75 |      0     |
|    0.75-0.99 |      2     |

每个比率分组是否有 1 个查询,我可以根据他们在表 2 中的分组来计算表 1 中的不同用户?我使用了 IF 和 COUNT 语句的组合,但表 1 中的每一行都被评估和计数,而不仅仅是 DISTINCT 用户,因此我得到了一个夸大的结果。

例如:

 COUNT((IF table1.user <0.25,1,0))
 COUNT((IF table1.user BETWEEN 0.25 AND 0.50,1,0))
 etc...

4 个查询中的每一个都将在存储过程中使用,因此每个比率分组需要 1 个查询,因此我可以将每个组的结果分配给存储过程中的变量。

【问题讨论】:

您有user_id 还是user 主键? “用户”是表 2 中的主键。表 1 中的主键是出价。 更正:在表 1 中,“出价”和唯一 ID 都是主键。表 1 将有多个与上述类似的示例。我没有为示例输入唯一 ID。 【参考方案1】:

您可以将SUMBETWEENDISTINCT 组合使用

SELECT
SUM(DISTINCT `table2`.`ratio` BETWEEN 0.00 AND 0.25) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) GROUP BY table1.user

SELECT
SUM(DISTINCT `table2`.`ratio` BETWEEN 0.25 AND 0.50) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) GROUP BY table1.user

SELECT
SUM(DISTINCT `table2`.`ratio` BETWEEN 0.50 AND 0.75 ) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) GROUP BY table1.user

SELECT
SUM(DISTINCT `table2`.`ratio` BETWEEN 0.75 AND 0.99) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) GROUP BY table1.user

或者你可以把它们组合成一个

SELECT  '0.00 - 0.25' Ratio_Group ,
SUM(DISTINCT `table2`.`ratio` BETWEEN 0.00 AND 0.25) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) GROUP BY table1.user
UNION ALL
SELECT '0.25 - 0.50' Ratio_Group ,
SUM(DISTINCT `table2`.`ratio` BETWEEN 0.25 AND 0.50) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) GROUP BY table1.user
UNION ALL
SELECT '0.50 - 0.75' Ratio_Group ,
SUM(DISTINCT `table2`.`ratio` BETWEEN 0.50 AND 0.75 ) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) GROUP BY table1.user
UNION ALL
SELECT '0.75 - 0.99' Ratio_Group ,
SUM(DISTINCT `table2`.`ratio` BETWEEN 0.75 AND 0.99) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) GROUP BY table1.user

编辑下面的查询将统计每个比率组的不同用户

SELECT  '0.00 - 0.25' Ratio_Group ,
COUNT(DISTINCT `table2`.`user` ) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) 
WHERE `table2`.`ratio` BETWEEN 0.00 AND 0.25

UNION ALL

SELECT '0.25 - 0.50' Ratio_Group ,
COUNT(DISTINCT `table2`.`user`) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) 
WHERE  `table2`.`ratio` BETWEEN 0.25 AND 0.50

UNION ALL

SELECT '0.50 - 0.75' Ratio_Group ,
COUNT(DISTINCT `table2`.`user` ) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) 
WHERE `table2`.`ratio` BETWEEN 0.50 AND 0.75
UNION ALL

SELECT '0.75 - 0.99' Ratio_Group ,
COUNT(DISTINCT `table2`.`user`) `count`
FROM table1 JOIN table2 ON (table1.user =table2.user) 
WHERE `table2`.`ratio` BETWEEN 0.75 AND 0.99

See Fiddle Demo

【讨论】:

这几乎可以工作,但是查询在“计数”字段中返回了几行。我需要为每个比率组返回 1 行。 我正在寻找更多这样的解决方案(4 个单独的查询 - 每个响铃 1 个)。上面的解决方案将每个用户作为一行返回,如果该用户在指定范围内,则为“1”,否则为“0”。如果表 1 中有 20 个用户,我会得到 20 个结果,而每个范围的总数应该只得到 1 个结果。我尝试在 SUM() 前面添加另一个 SUM() 认为它只会将所有 1 相加,但它给出了一个错误。 @user1885697 查看我的更新答案以及see fiddle demo here 编辑效果很好。我可以在没有 UNION ALL 的情况下使用每个查询,它适用于我需要的每个比率组。谢谢!!【参考方案2】:

如果您不介意只抓取有成员的群组,您可以执行以下操作。它使用内部查询来获取唯一成员及其相应的比率,然后使用包含表按这些比率将它们分组到比率组中。好消息是你没有硬编码行组,这不是很像 SQL;缺点是您看不到计数为 0 的行“成员”。

SELECT
    CONCAT(
        ((CEIL(ratio * 4) * 0.25 ) - 0.25),
        " - ",
        (CEIL( ratio *4 ) * 0.25)
    ) AS ratio_group,
    COUNT(user) AS user_count
FROM (
    SELECT
        t1.user,
        t2.ratio
    FROM
        `table1` t1
    INNER JOIN
        `table2` t2 ON t2.user = t1.user
    GROUP BY
        t1.user
) virtual_table
GROUP BY
    CEIL(ratio * 4)

根据您的附加 cmets,您可以将所有数据组合成一个字符串,然后像这样分配给一个变量。这是一个混蛋的地狱。你如何处理这些数据(此时它本质上是一个 CSV 字符串)取决于你,哈哈。

@data = 
(SELECT
    GROUP_CONCAT(combined SEPARATOR ';')
FROM (
    SELECT
        CONCAT(
            '"',
            CONCAT(
                ((CEIL(ratio * 4) * 0.25) - 0.25),
                " - ",
                (CEIL( ratio *4 ) * 0.25)
            ),
            '",',
            COUNT( user )
        ) AS combined
    FROM (
        SELECT
            t1.user,
            t2.ratio
        FROM 
            `table1` t1
        INNER JOIN
            `table2` t2 ON t2.user = t1.user
        GROUP BY
            t1.user
    ) virtual_table
    GROUP BY
        CEIL( ratio *4 )
) virtual_table2 )

【讨论】:

这似乎运作良好,但我如何修改,以便每个比率字段分别返回?我需要将每个总和值分配给存储过程中的一个变量。 除非有办法将每一行分配给一个变量? 我给你的第二个查询会给你一个像这样的单元格结果:"0.00 - 0.25",1;"0.25 - 0.50",1;"0.75 - 1.00",2 好吧,我觉得有点傻,但是每个组应该分配给单个变量,或者我如何选择@data中的4个数据价格中的1个用于公式中?该公式要求在公式的不同部分使用每个变量。最终我需要像'@range1'这样的东西; '@range2'; '@range3';和 '@range4' 代表每个四分位数。

以上是关于MySQL在1个表中选择不同的记录并根据另一个表中的值计算每个组的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 根据记录是不是存在于另一个表中选择布尔值

oracle SQL left join()或full out join()根据键排除记录

MySQL 从 3 个表中选择不同的产品

mysql查询加入,比较两个表并返回第一个表中的所有记录

Postgresql从具有不同列数的2个表中选择多条记录

mysql插入tbl(从2个表中选择)