获得范围之间的金额

时间:2013-12-01 03:50:05

标签: mysql sql sql-server

这是一个简单的我的表

+-----------+----------------+-----------+
|     id    |       date     |   meter   |
------------+----------------+-----------+
|      1    |  2103-11-01    |   5       |
|      2    |  2103-11-10    |   8       |
|      4    |  2103-11-14    |   10      |
|      6    |  2103-11-20    |   18      |
|      7    |  2103-11-25    |   25      |
|      10   |  2103-11-29    |   30      |
+-----------+----------------+-----------+

如何在两个记录时间范围之间得到米的使用结果, 像贝娄一样

+----------------+----------------+-------+-----+--------+ 
|    date1       |    date2       | start | end | amount | 
+----------------+----------------+-------+-----+--------+
|    2013-11-01  |    2013-11-10  |  5    |  8  |  3     | 
|    2013-11-10  |    2013-11-14  |  8    | 10  |  2     | 
|    2013-11-14  |    2013-11-20  | 10    | 18  |  8     | 
|    2013-11-20  |    2013-11-25  | 18    | 25  |  7     | 
|    2013-11-25  |    2013-11-29  | 25    | 30  |  5     | 
+----------------+----------------+-------+-----+--------+

5 个答案:

答案 0 :(得分:1)

编辑: 我明白了:

select meters1.date as date1, min(meters2.date) as date2, meters1.meter as start,
  meters2.meter as end, (meters2.meter - meters1.meter) as amount
  from meters meters1, meters meters2 where meters1.date < meters2.date
   group by date1;

输出:

+------------+------------+-------+-----+--------+
| date1      | date2      | start | end | amount |
+------------+------------+-------+-----+--------+
| 2013-11-01 | 2013-11-10 |     5 |   8 |      3 |
| 2013-11-10 | 2013-11-14 |     8 |  10 |      2 |
| 2013-11-14 | 2013-11-20 |    10 |  18 |      8 |
| 2013-11-20 | 2013-11-25 |    18 |  25 |      7 |
| 2013-11-25 | 2013-11-29 |    25 |  30 |      5 |
+------------+------------+-------+-----+--------+

原帖:

这就是大部分时间:

select meters1.date as date1, meters2.date as date2, meters1.meter as start,
  meters2.meter as end, (meters2.meter - meters1.meter) as amount
  from meters meters1, meters meters2 having date1 < date2 order by date1;

输出:

+------------+------------+-------+-----+--------+
| date1      | date2      | start | end | amount |
+------------+------------+-------+-----+--------+
| 2013-11-01 | 2013-11-10 |     5 |   8 |      3 |
| 2013-11-01 | 2013-11-20 |     5 |  18 |     13 |
| 2013-11-01 | 2013-11-29 |     5 |  30 |     25 |
| 2013-11-01 | 2013-11-14 |     5 |  10 |      5 |
| 2013-11-01 | 2013-11-25 |     5 |  25 |     20 |
| 2013-11-10 | 2013-11-20 |     8 |  18 |     10 |
| 2013-11-10 | 2013-11-29 |     8 |  30 |     22 |
| 2013-11-10 | 2013-11-14 |     8 |  10 |      2 |
| 2013-11-10 | 2013-11-25 |     8 |  25 |     17 |
| 2013-11-14 | 2013-11-25 |    10 |  25 |     15 |
| 2013-11-14 | 2013-11-20 |    10 |  18 |      8 |
| 2013-11-14 | 2013-11-29 |    10 |  30 |     20 |
| 2013-11-20 | 2013-11-25 |    18 |  25 |      7 |
| 2013-11-20 | 2013-11-29 |    18 |  30 |     12 |
| 2013-11-25 | 2013-11-29 |    25 |  30 |      5 |
+------------+------------+-------+-----+--------+

答案 1 :(得分:1)

如果它的SQL服务器以这种方式尝试

WITH cte AS
(
  SELECT *, ROW_NUMBER() OVER (ORDER BY date) rnum
    FROM table1
)
SELECT c.date date1, p.date date2, c.meter [start], p.meter [end], p.meter - c.meter amount
  FROM cte c JOIN cte p
    ON c.rnum = p.rnum - 1

这是 SQLFiddle 演示


如果是MySQL,那么你可以做

SELECT date1, date2, meter1, meter2, meter2 - meter1 amount
  FROM
(
  SELECT @d date2, date date1, @m meter2, meter meter1, @d := date, @m := meter
    FROM table1 CROSS JOIN (SELECT @d := NULL, @m := NULL) i
   ORDER BY date DESC
) q
 WHERE date2 IS NOT NULL
 ORDER BY date1

这是 SQLFiddle 演示

两种情况下的输出:

|      DATE1 |      DATE2 | START | END | AMOUNT |
|------------|------------|-------|-----|--------|
| 2103-11-01 | 2103-11-10 |     5 |   8 |      3 |
| 2103-11-10 | 2103-11-14 |     8 |  10 |      2 |
| 2103-11-14 | 2103-11-20 |    10 |  18 |      8 |
| 2103-11-20 | 2103-11-25 |    18 |  25 |      7 |
| 2103-11-25 | 2103-11-29 |    25 |  30 |      5 |

答案 2 :(得分:1)

的MySQL

SELECT DATES.date1,
       DATES.date2,
       m1.meter as start,
       m2.meter as end,
       m2.meter - m1.meter as amount
FROM
  (SELECT date as date1,
       (SELECT min(date)
        FROM tableName t2
        WHERE t2.date > t1.date) as date2
   FROM tableName t1
  )DATES,
  tableName m1,
  tableName m2
WHERE DATES.date2 IS NOT NULL
  AND m1.date = DATES.date1
  AND m2.date = DATES.date2
ORDER BY DATES.date1

sqlFiddle here

MS-SQL SERVER 2002中的

将单词end更改为"end",因为它抱怨end附近的语法

答案 3 :(得分:0)

如果你正在使用MySQL,那么自联接在这里会很好用。使用ON子句将表连接到自身,以确保不将相同的记录连接到自身。这将为您提供数据的((N * N) - N)个排列,其中N是原始行的数量。

SELECT
    ...
FROM
    tableName first
JOIN
    tableName second
    ON first.id != second.id

然后,所有关于SELECT正确的东西(包括计算两个meter值之间的差异)。要获取您发布的结果集中的列,您可能需要SELECT

first.date AS date1,
second.date AS date2,
first.meter AS start,
second.meter AS end,
ABS(first.meter - second.meter) AS amount

修改的 啊,我明白了。我设想过你曾经在路线图上看到的城际里程图(你在行和列中有相同的城市,交叉点中的单元格表示这两者之间的里程数)城市。

但看起来您只想比较一个日期与下一个日期的值。如果是这种情况,你可以利用MySQL处理GROUPORDER的方式...但要小心,因为我不确定这是否有保证:

mysql> SELECT 
    table1.date AS date1, 
    table2.date AS date2, 
    table1.meter AS start, 
    table2.meter AS end, 
    ABS(table1.meter - table2.meter) AS amount 
FROM tableName table1 
JOIN tableName table2 
    WHERE table2.date > table1.date 
GROUP BY table1.date 
ORDER BY table2.date - table1.date;
+---------------------+---------------------+-------+------+--------+
| date1               | date2               | start | end  | amount |
+---------------------+---------------------+-------+------+--------+
| 2103-11-25 00:00:00 | 2103-11-29 00:00:00 |    25 |   30 |      5 |
| 2103-11-10 00:00:00 | 2103-11-14 00:00:00 |     8 |   10 |      2 |
| 2103-11-20 00:00:00 | 2103-11-25 00:00:00 |    18 |   25 |      7 |
| 2103-11-14 00:00:00 | 2103-11-20 00:00:00 |    10 |   18 |      8 |
| 2103-11-01 00:00:00 | 2103-11-10 00:00:00 |     5 |    8 |      3 |
+---------------------+---------------------+-------+------+--------+
5 rows in set (0.00 sec)

答案 4 :(得分:0)

您还没有说清楚您是否真的使用mySQL或SQL Server,但我发布的解决方案适用于SQL 2008及更高版本。可能会在2005年工作,但我无法测试。

-- Set up a temp table with sample data
DECLARE @testData AS TABLE(
    id int,
    dt date,
    meter int)

INSERT @testData(id, dt, meter) VALUES 
     (1, '2013-11-01', 5)
    ,(2, '2013-11-10', 8)
    ,(4, '2013-11-14', 10)
    ,(6, '2013-11-20', 18)
    ,(7, '2013-11-25', 25)
    ,(10, '2013-11-29',30)
---------------------------------------------

-- Begin SQL Server solution
;WITH cte AS (
    SELECT 
        ROW_NUMBER() OVER (ORDER BY id) AS rownum
        ,id
        ,dt
        ,meter
    FROM 
        @testData AS [date2] 
)

SELECT 
     t1.id
    ,t1.dt AS [date1]
    ,t2.dt AS [date2]
    ,t1.meter AS [start]
    ,t2.meter AS [end]
    ,t2.meter - t1.meter AS [amount]
FROM 
    cte t1 
    LEFT OUTER JOIN cte t2 ON (t2.rownum = t1.rownum + 1)
WHERE 
    t2.dt IS NOT NULL