【问题标题】:Performing an arbitrary number of self joins in mySQL [duplicate]在 mySQL 中执行任意数量的自连接 [重复]
【发布时间】:2013-10-01 10:47:40
【问题描述】:

我在 mysql 中有一个数据集,其中包含多个命名接口的带宽测试结果,以及执行测试的日期和接口的名称。示例数据集如下所示:

|  date  |  testResult  |  interface  |
---------------------------------------
| 12/25  |     32       |    eth0     |
| 12/25  |     21       |    eth0     |
| 12/25  |     25       |    eth0     |
| 12/26  |     30       |    eth0     |
| 12/27  |     33       |    eth0     |
| 12/25  |     12       |    eth1     |
| 12/25  |     16       |    eth1     |
| 12/27  |     3        |    vz0      |
| 12/26  |     120      |    virt1    |

我需要绘制给定日期每个界面的平均结果,所以我目前的解决方案是

SELECT `date`, AVG(`testResult`) as avg, `interface` FROM `tests` WHERE 1=1 
GROUP BY date, interface ORDER BY interface, date

这给了我这样的结果

|  date  |     avg      |  interface  |
---------------------------------------
| 12/25  |     26       |    eth0     |
| 12/26  |     30       |    eth0     |
| 12/27  |     33       |    eth0     |
| 12/25  |     14       |    eth1     |
| 12/26  |     120      |    virt1    |
| 12/27  |     3        |    vz0      |

我的问题是我需要在日期“加入”(我认为)这些数据,并为当天每个接口的平均值提供一列。结果集中接口的名称和数量不是恒定的,不能硬编码。我理想的结果集如下所示:

|  date  |  avg_eth0    |  avg_eth1   |  avg_virt1   |  avg_vz0   |
-------------------------------------------------------------------
| 12/25  |     26       |      14     |    NULL      |    NULL    |
| 12/26  |     30       |      NULL   |    120       |    NULL    |
| 12/27  |     33       |      NULL   |    NULL      |    3       |

有没有办法执行这个连接,基本上为interface 列的每个唯一值创建一个列?

【问题讨论】:

  • 跨选项卡在 mysql 中实际上是不可能的,您需要应用程序级代码。见also this answer
  • 可以生成查询然后执行吗?有非常公式化的查询可以做到这一点,但您需要先查询哪些值在那里..或者只是在 excel 中使用数据透视表;)

标签: mysql sql join pivot-table self-join


【解决方案1】:

在不知道数据透视表中列的不同值的情况下,您无法以任何形式的 SQL 生成数据透视表查询。

换句话说,您必须对每个界面的一列进行硬编码,如@David Jashi 的回答所示。

但这意味着您需要先了解接口的不同值,然后才能编写 SQL 查询。作为第一步,您可以通过运行查询来非常简单地做到这一点:

SELECT DISTINCT interface FROM `tests`;

然后循环遍历结果,将更多列附加到 SQL 查询中以执行数据透视。

抱歉,SQL 无法查询接口,并且在同一查询中动态添加更多列,因为它遇到数据中的不同值。您需要运行两个查询。

【讨论】:

    【解决方案2】:

    我建议使用旋转:

    select date,
    AVG(case when interface='eth0' then avg else 0)) as eth0,
    AVG(case when interface='eth0' then avg else 0)) as eth1,
    AVG(case when interface='virt1' then avg else 0)) as virt1,
    AVG(case when interface='vz0' then avg else 0)) as vz0
    from (
    SELECT `date`, AVG(`testResult`) as avg, `interface` FROM `tests` WHERE 1=1 
    GROUP BY date, interface ORDER BY interface, date) as z group by date
    

    【讨论】:

      猜你喜欢
      • 2010-09-16
      • 2015-05-22
      • 1970-01-01
      • 2018-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-01
      • 1970-01-01
      相关资源
      最近更新 更多