【问题标题】:How to ensure that a ResultSet includes rows for "missing" observations如何确保 ResultSet 包含“缺失”观察的行
【发布时间】:2025-12-26 09:30:09
【问题描述】:

我有一个如下所示的 ResultSet 表:

+------------+--------------------+--------------------+---------+-----------------------+
| test_date  | upload_kbps        | download_kbps      | latency | network_operator_name |
+------------+--------------------+--------------------+---------+-----------------------+
| 2017-04-02 |  19.12741903076923 | 44.614721153846155 | 32.1250 | Alcatel               |           
| 2017-03-31 |  18.30683616557377 | 44.294387978142076 | 34.7432 | Alcatel               |
| 2017-03-31 | 20.643555595555555 |  50.99801587301587 | 32.1640 | Vodafone              |

我想修改 ResultSet 以供进一步使用,同时我将一行添加到 ResultSet 中,如下所示:

    +------------+--------------------+--------------------+---------+-----------------------+
    | test_date  | upload_kbps        | download_kbps      | latency | network_operator_name |
    +------------+--------------------+--------------------+---------+-----------------------+
    | 2017-04-02 |  19.12741903076923 | 44.614721153846155 | 32.1250 | Alcatel               |   
    | 2017-04-02 |  0                 | 0                  | 0       | Vodafone              |        
    | 2017-03-31 |  18.30683616557377 | 44.294387978142076 | 34.7432 | Alcatel               |
    | 2017-03-31 | 20.643555595555555 |  50.99801587301587 | 32.1640 | Vodafone              |

这背后的逻辑基本上是为该电信添加一个空行,那天没有对其进行速度测试。为了进一步澄清:我需要这样做的原因是因为 MySQL db 中的表没有记录未完成的测试的行/条目,因此在我的原始 ResultSet 中缺少一行,因此我需要添加一个' NULL/0' 行,以反映那天该电信公司缺乏测试。我目前无法直接访问该数据库来修改条目,所以这是我能想到的最好的。

知道我该怎么做吗?感谢您的帮助!

【问题讨论】:

    标签: java mysql sql jdbc resultset


    【解决方案1】:

    听起来您想在事后向 ResultSet 添加行。 AFAIK,我们不能那样做。相反,我们需要构造我们的 SQL 查询,以便它生成我们需要的“额外”行。

    所以如果我们有一个名为“test”的表并且

    SELECT * FROM test
    ORDER BY test_date DESC, network_operator_name
    

    生产

    test_date   upload_kbps       download_kbps     latency  network_operator_name
    ----------  ----------------  ----------------  -------  ---------------------
    2017-04-02  19.1274190307692  44.6147211538461   32.125  Alcatel              
    2017-03-31  18.3068361655737   44.294387978142  34.7432  Alcatel              
    2017-03-31  20.6435555955555  50.9980158730158   32.164  Vodafone             
    

    然后我们可以从查询开始,为test_datenetwork_operator_name 的每个组合生成一行

    SELECT test_date, network_operator_name
    FROM
        (SELECT DISTINCT network_operator_name FROM test) unique_operators
        CROSS JOIN
        (SELECT DISTINCT test_date FROM test) unique_dates
    

    这给了我们

    test_date   network_operator_name
    ----------  ---------------------
    2017-03-31  Alcatel              
    2017-03-31  Vodafone             
    2017-04-02  Alcatel              
    2017-04-02  Vodafone             
    

    然后我们可以将查询与实际表 LEFT JOIN

    SELECT 
        required_rows.test_date,
        COALESCE(test.upload_kbps, 0) AS upload_kbps,
        COALESCE(test.download_kbps, 0) AS download_kbps,
        COALESCE(test.latency, 0) AS latency,
        required_rows.network_operator_name
    FROM 
        (
            SELECT test_date, network_operator_name
            FROM
                (SELECT DISTINCT network_operator_name FROM test) unique_operators
                CROSS JOIN
                (SELECT DISTINCT test_date FROM test) unique_dates
        ) required_rows
        LEFT JOIN
        test
            ON required_rows.test_date = test.test_date 
                AND required_rows.network_operator_name = test.network_operator_name
    ORDER BY required_rows.test_date DESC, required_rows.network_operator_name
    

    生产

    test_date   upload_kbps       download_kbps     latency  network_operator_name
    ----------  ----------------  ----------------  -------  ---------------------
    2017-04-02  19.1274190307692  44.6147211538461   32.125  Alcatel              
    2017-04-02                 0                 0        0  Vodafone             
    2017-03-31  18.3068361655737   44.294387978142  34.7432  Alcatel              
    2017-03-31  20.6435555955555  50.9980158730158   32.164  Vodafone             
    

    【讨论】:

    • 出色的答案,完美运行,加分,感谢您花时间逐步解释它,以便像我这样的 mysql 新手也能理解它。我真的需要开始思考超越简单的选择/更新语句 =/
    【解决方案2】:

    你可以使用mysql的NULLIF()函数。在函数中,您提供了您测试速度测试是否完成的变量。假设当那天没有进行速度测试时,延迟为零。

    那么NULLIF(latency,0) 将是插入命令中列延迟的值。因此对于其他列,您需要在某些条件下填充 NULL。如果 第一个参数第二个参数 匹配,此函数返回 NULL。否则给出第一个参数的实际值

    【讨论】:

    • 我在这里有点困惑。也许我可以澄清一下,当没有对电信公司进行测试时,mysql 数据库中没有条目,因此我的原始 ResultSet 中缺少行,因此我需要为该电信公司手动输入一个额外的“NULL”行那天。如果我在谷歌搜索中没有弄错的话,如果 mysql 数据库表中的该电信公司的表中已经有一个零值,而没有进行任何测试,那么 NULLIF() 是否有效?
    • 那么,如果某电信公司当天没有记录,您想要一行没有特定电信公司的值吗?那你有固定的电信公司名单吗?
    • 是的,我有一个固定的电信公司名单,如果你的意思是由我将使用的电信公司固定(仅提及两个,仅此而已)
    • 显示报告你在用什么?您可以在当天加载报告,通过遍历结果集来填充每一行的值,当您没有得到任何结果时,您可以在该行上显示零。如果使用 php 脚本,您可以通过这种方式创建表格行组合。或者,当您为电信公司 speedtest 的条目填充数据库表时,您可以在没有值的电信公司的行中插入零。可以通过这种方式实现数据库中只有电信名称的整行和其他具有 NULL 或零的列。