mysql 按日期获取单位消耗

edqdpe6u  于 2024-01-05  发布在  Mysql
关注(0)|答案(4)|浏览(117)

我挣扎着从mysql中得到结果如下。我有10个记录在mysql数据库表有日期和单位字段。我需要得到每个日期使用的单位。
表结构如下,在每条记录中添加今天的单位和过去的前一个单位:

  1. Date Units
  2. ---------- ---------
  3. 10/10/2012 101
  4. 11/10/2012 111
  5. 12/10/2012 121
  6. 13/10/2012 140
  7. 14/10/2012 150
  8. 15/10/2012 155
  9. 16/10/2012 170
  10. 17/10/2012 180
  11. 18/10/2012 185
  12. 19/10/2012 200

字符串
所需的输出将是:

  1. Date Units
  2. ---------- ---------
  3. 10/10/2012 101
  4. 11/10/2012 10
  5. 12/10/2012 10
  6. 13/10/2012 19
  7. 14/10/2012 10
  8. 15/10/2012 5
  9. 16/10/2012 15
  10. 17/10/2012 10
  11. 18/10/2012 5
  12. 19/10/2012 15


任何帮助都将不胜感激。谢谢

avkwfej4

avkwfej41#

有几种方法可以得到结果集。如果你能接受结果集中的一个额外的列,以及列的顺序,那么像这样的方法是可行的。

使用用户变量

  1. SELECT d.Date
  2. , IF(@prev_units IS NULL
  3. ,@diff := 0
  4. ,@diff := d.units - @prev_units
  5. ) AS `Units_used`
  6. , @prev_units := d.units AS `Units`
  7. FROM ( SELECT @prev_units := NULL ) i
  8. JOIN (
  9. SELECT t.Date, t.Units
  10. FROM mytable t
  11. ORDER BY t.Date, t.Units
  12. ) d

字符串
这将返回指定的结果集,但它也包括Units列。可以过滤掉该列,但由于MySQL处理内联视图的方式(MySQL称之为“派生表”),因此成本更高。
要删除该额外列,可以将其 Package 在另一个查询中...

  1. SELECT f.Date
  2. , f.Units_used
  3. FROM (
  4. query from above goes here
  5. ) f
  6. ORDER BY f.Date


但是,再次删除该列会带来第二次具体化该结果集的额外成本。

使用半连接

如果你保证每个Date值都有一行,或者存储为一个日期,或者存储为一个DATETIME,其中时间组件设置为一个常量,比如午夜,并且日期值中没有间隔,并且日期定义为日期或DATETIME数据类型,那么另一个查询将返回特定的结果集:

  1. SELECT t.Date
  2. , t.Units - s.Units AS Units_Used
  3. FROM mytable t
  4. LEFT
  5. JOIN mytable s
  6. ON s.Date = t.Date + INTERVAL -1 DAY
  7. ORDER BY t.Date


如果缺少Date值(间隙),使得没有匹配的前一行,则Units_used将具有NULL值。

使用相关子查询

如果你不能保证没有“缺失的日期”,但是你可以保证一个特定的日期不超过一行,那么另一种方法(通常在性能方面更昂贵)是使用相关的子查询:

  1. SELECT t.Date
  2. , ( t.Units - (SELECT s.Units
  3. FROM mytable s
  4. WHERE s.Date < t.Date
  5. ORDER BY s.Date DESC
  6. LIMIT 1)
  7. ) AS Units_used
  8. FROM mytable t
  9. ORDER BY t.Date, t.Units

展开查看全部
hfsqlsce

hfsqlsce2#

spencer7593的解决方案会更快,但你也可以这样做.

  1. SELECT * FROM rolling;
  2. +----+-------+
  3. | id | units |
  4. +----+-------+
  5. | 1 | 101 |
  6. | 2 | 111 |
  7. | 3 | 121 |
  8. | 4 | 140 |
  9. | 5 | 150 |
  10. | 6 | 155 |
  11. | 7 | 170 |
  12. | 8 | 180 |
  13. | 9 | 185 |
  14. | 10 | 200 |
  15. +----+-------+
  16. SELECT a.id,COALESCE(a.units - b.units,a.units) units
  17. FROM
  18. ( SELECT x.*
  19. , COUNT(*) rank
  20. FROM rolling x
  21. JOIN rolling y
  22. ON y.id <= x.id
  23. GROUP
  24. BY x.id
  25. ) a
  26. LEFT
  27. JOIN
  28. ( SELECT x.*
  29. , COUNT(*) rank
  30. FROM rolling x
  31. JOIN rolling y
  32. ON y.id <= x.id
  33. GROUP
  34. BY x.id
  35. ) b
  36. ON b.rank= a.rank -1;
  37. +----+-------+
  38. | id | units |
  39. +----+-------+
  40. | 1 | 101 |
  41. | 2 | 10 |
  42. | 3 | 10 |
  43. | 4 | 19 |
  44. | 5 | 10 |
  45. | 6 | 5 |
  46. | 7 | 15 |
  47. | 8 | 10 |
  48. | 9 | 5 |
  49. | 10 | 15 |
  50. +----+-------+

字符串

展开查看全部
a5g8bdjr

a5g8bdjr3#

这应该给予想要的结果。我不知道你的表是如何命名的,所以我命名它为“tbltest”。创建一个表日期通常是一个坏主意,因为它也指其他事情(函数、数据类型、在字段名或表名中使用fdate字符也是一个坏主意,因为它会使语句不那么独立于数据库(有些数据库区分大小写,有些不区分大小写)。

  1. SELECT
  2. A.fdate,
  3. A.units - coalesce(B.units, 0) AS units
  4. FROM
  5. tbltest A left join tbltest B ON A.fdate = B.fdate + INTERVAL 1 DAY

字符串

jjjwad0x

jjjwad0x4#

SELECT A.units AS current_units,IFNULL(A.units - LAG(A.units)OVER(ORDER BY A.id),A.units)AS difference FROM tbltest A;

相关问题