【问题标题】:MySQL - Show record pairs in one recordMySQL - 在一条记录中显示记录对
【发布时间】:2011-08-11 02:20:20
【问题描述】:

我在一张表中有以下数据:

Time, Type, Kilometers
12:00, 1, 0.1
12:30, 2, 0.2
14:00, 1, 0.4
15:00, 2, 1.0
16:00, 1, 1.2
16:30, 2, 1.5
16:45, 1, 2.0

此数据使用 DateTime 字段按时间顺序排序。我想将这些记录“对”显示为 1 行,如下所示:

StartTime, Type1Km, Type2Km
12:00, 0.1, 0.2
14:00, 0.4, 1.0
16:00, 1.2, 1.5
16:45, 2.0, NULL

有几个注意事项:如果没有要启动的 Type1,则在结果表的 Type1Km 字段中显示 NULL。同样,如果没有 Type2 结束,则在记录的 Type2Km 字段中显示 NULL。

我该怎么做?

【问题讨论】:

  • 棘手的部分是你加入了类型 1 的时间和类型 2 的下一次。如果有 2 个类型 1 的“连续”,那么 Type2Km 应该为空,对吧?
  • @MPelletier - 正确(这不太可能发生,但如果解决方案考虑到这一点将是有益的)
  • 如果这个表有一个自动增量列来将 X 链接到 X+1 以进行差分测试,我会更容易处理......有没有,只是上面没有显示?跨度>
  • 进一步了解@DRapp 的问题:这可靠吗?时间会按顺序插入吗?
  • @DRapp,有,但是不能保证(并且可能不会)type2 = X+1

标签: mysql sql join


【解决方案1】:

不幸的是,MySQL 缺少 FULL OUTER JOIN,因此您必须将 UNION 两组放在一起。

这将为您提供Type1Km 存在的情况,无论Type2Km 是否存在。

SELECT
    t1.`Time` as StartTime,
    t1.`Kilometers` as Type1Km,
    t2.`Kilometers` as Type2Km
FROM `times` t1
LEFT JOIN `times` t2 ON t2.`Type` = 2
                    AND t2.`Time` = (SELECT `Time` FROM `times`
                                     WHERE `Time` > t1.`Time`
                                     ORDER BY `Time` LIMIT 1)
WHERE t1.`Type` = 1

现在我们需要Type1Km 不存在的情况。

SELECT
    t2.`Time` as StartTime,
    NULL as Type1Km,
    t2.`Kilometers` as Type2Km
FROM `times` t2
LEFT JOIN `times` t1 ON t1.`Time` = (SELECT `Time` FROM `times`
                                     WHERE `Time` < t2.`Time`
                                     ORDER BY `Time` DESC LIMIT 1)
WHERE t2.`Type` = 2
  AND (t1.`Type` = 2 OR t1.`Type` IS NULL)

UNION 将它们放在一起,你就会得到想要的结果:

(
SELECT
    t1.`Time` as StartTime,
    t1.`Kilometers` as Type1Km,
    t2.`Kilometers` as Type2Km
FROM `times` t1
LEFT JOIN `times` t2 ON t2.`Type` = 2
                    AND t2.`Time` = (SELECT `Time` FROM `times`
                                     WHERE `Time` > t1.`Time`
                                     ORDER BY `Time` LIMIT 1)
WHERE t1.`Type` = 1

) UNION ALL (

SELECT
    t2.`Time` as StartTime,
    NULL as Type1Km,
    t2.`Kilometers` as Type2Km
FROM `times` t2
LEFT JOIN `times` t1 ON t1.`Time` = (SELECT `Time` FROM `times`
                                     WHERE `Time` < t2.`Time`
                                     ORDER BY `Time` DESC LIMIT 1)
WHERE t2.`Type` = 2
  AND (t1.`Type` = 2 OR t1.`Type` IS NULL)
)

ORDER BY `StartTime`

更新

在我之前的查询中,我忘记在一开始就有“类型 2”记录。更新以说明这一点。这是我得到的结果:

times 表中的数据:

+----------+------+------------+
| Time     | Type | Kilometers |
+----------+------+------------+
| 11:00:00 |    2 |        0.1 |
| 12:00:00 |    1 |        0.1 |
| 12:30:00 |    2 |        0.2 |
| 14:00:00 |    1 |        0.4 |
| 14:30:00 |    1 |        0.8 |
| 15:00:00 |    2 |        1.0 |
| 15:30:00 |    2 |        0.2 |
| 16:00:00 |    1 |        1.2 |
| 16:30:00 |    2 |        1.5 |
| 16:45:00 |    1 |        2.0 |
+----------+------+------------+

查询结果:

+-----------+---------+---------+
| StartTime | Type1Km | Type2Km |
+-----------+---------+---------+
| 11:00:00  |    NULL |     0.1 |
| 12:00:00  |     0.1 |     0.2 |
| 14:00:00  |     0.4 |    NULL |
| 14:30:00  |     0.8 |     1.0 |
| 15:30:00  |    NULL |     0.2 |
| 16:00:00  |     1.2 |     1.5 |
| 16:45:00  |     2.0 |    NULL |
+-----------+---------+---------+

【讨论】:

    【解决方案2】:

    如果可以,请将表结构更改为 type1km 和 type2km,然后在添加 kms 时更新或在选择时进行汇总。

    【讨论】:

      【解决方案3】:

      这可能有效

      select 
      max(Time), 
      substring_index(group_concat(if(type=2,null,Kilometers) order by type),',',1),
      substring_index(group_concat(if(type=1,null,Kilometers) order by type desc),',',1) 
      from your_table 
      group by date_format(Time, '%H');
      

      我假设按小时分组,而且你的示例结果也不准确

      为了更好地解释这个有趣的查询的作用

      group_concat(if(type=2,null,Kilometers) order by type
      -- this is ensure the Kilometers must NOT from type=2
      
      group_concat(if(type=1,null,Kilometers) order by type desc
      -- this is ensure the Kilometers must NOT from type=1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-19
        • 1970-01-01
        • 1970-01-01
        • 2013-08-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多