MySQL UNION ALL通过超前滞后提供不需要的值

时间:2018-04-06 06:57:30

标签: mysql sql join union-all

我有一个查询,它会单独生成正确的值。我看到act_in_sec< 0应该result no values哪里是正确的,只有在我使用相同的查询但不同的机器进行联合时才会出现问题。我不确定会出现什么问题。

    Select Y.machine, Y.start_time, Y.end_time, TIMEDIFF(Y.end_time,Y.start_time) as act,
    TIME_TO_SEC(TIMEDIFF(Y.end_time,Y.start_time)) act_in_sec
    FROM
    (
    select X.machine, X.ts as start_time, X.next_ts as end_time
    from (
    select
    *
    , @prev AS next_ts
    , @prev := ts
    from
    (select * from machinestatushistory where machine = 'XXX23-4-XX' order by ts desc) AA
    , (select @prev:=NULL) vars where machine = 'XXX23-4-XX'
    order by ts desc
    ) X WHERE X.MACHINE = 'XXX23-4-XX'

我正在做UNION ALL,如下所示。

select * from (
Select Y.machine, Y.start_time, Y.end_time, TIMEDIFF(Y.end_time,Y.start_time) as act,
TIME_TO_SEC(TIMEDIFF(Y.end_time,Y.start_time)) act_in_sec
FROM
(
select X.machine, X.ts as start_time, X.next_ts as end_time
from (
select
*
, @prev AS next_ts
, @prev := ts
from
(select * from machinestatushistory where machine = 'XXX23-4-XX' order by ts desc) AA
, (select @prev:=NULL) vars where machine = 'XXX23-4-XX'
order by ts desc
) X WHERE X.MACHINE = 'XXX23-4-XX'
)Y

UNION ALL

Select A.machine, A.start_time, A.end_time, TIMEDIFF(A.end_time,A.start_time) as act,
TIME_TO_SEC(TIMEDIFF(A.end_time,A.start_time)) act_in_sec
FROM
(
select B.machine, B.ts as start_time, B.next_ts as end_time
from (
select
*
, @prev AS next_ts
, @prev := ts
from
(select * from machinestatushistory where machine = 'XXX23-42-XX' order by ts desc) AA
, (select @prev:=NULL) vars where machine = 'XXX23-42-XX'
order by ts desc
) B WHERE B.MACHINE = 'XXX23-42-XX'
)A
)W where act_in_sec<0

无论我如何订购查询,我只能从第二个选择中的机器获取错误的值。

2 个答案:

答案 0 :(得分:1)

可能根本不是你的问题,但@prev没有在两个语句之间初始化,例如

select t.id,t.username , @prev:=@prev + 1 prev,0 as prev1
from users t,(select @prev:=0) p
union all
select t.id,t.username , @prev:=@prev + 1,@prev1:=@prev1+1 as prev1
from users t,(select @prev:=0,@prev1:=0) p1;

+----+----------+------+-------+
| id | username | prev | prev1 |
+----+----------+------+-------+
|  1 | John     |    1 |     0 |
|  2 | Jane     |    2 |     0 |
|  3 | Ali      |    3 |     0 |
|  6 | Bruce    |    4 |     0 |
|  7 | Martha   |    5 |     0 |
|  8 | Sidney   |    6 |     0 |
| 10 | charlie  |    7 |     0 |
| 12 | Elisa    |    8 |     0 |
| 14 | Samantha |    9 |     0 |
| 15 | Hannah   |   10 |     0 |
| 16 | Hannah   |   11 |     0 |
| 17 | Kevin    |   12 |     0 |
| 18 | Kevin    |   13 |     0 |
| 19 | Ruth     |   14 |     0 |
|  1 | John     |   15 |     1 |
|  2 | Jane     |   16 |     2 |
|  3 | Ali      |   17 |     3 |
|  6 | Bruce    |   18 |     4 |
|  7 | Martha   |   19 |     5 |
|  8 | Sidney   |   20 |     6 |
| 10 | charlie  |   21 |     7 |
| 12 | Elisa    |   22 |     8 |
| 14 | Samantha |   23 |     9 |
| 15 | Hannah   |   24 |    10 |
| 16 | Hannah   |   25 |    11 |
| 17 | Kevin    |   26 |    12 |
| 18 | Kevin    |   27 |    13 |
| 19 | Ruth     |   28 |    14 |
+----+----------+------+-------+
28 rows in set (0.00 sec)

答案 1 :(得分:0)

找到一种不同的方法来做到这一点。使用case并按机器排序 - 将下一台机器的第一个值设置为NULL,然后设置差异。

select * from (Select Y.machine, Y.start_time, Y.end_time, TIMEDIFF(Y.end_time,Y.start_time) as act,
TIME_TO_SEC(TIMEDIFF(Y.end_time,Y.start_time)) act_in_sec
FROM
(
select X.machine, X.ts as start_time, X.next_ts as end_time
from (
select

*
, case when machine=@prevMac
then @prev 
else NULL end AS next_ts
, @prevMac := machine
, @prev := ts
from
(select * from machinestatushistory where machine in ('XXX23-4-XX','XXX23-42-XX') order by machine,ts desc) AA
, (select @prev:=NULL, @prevMac:=NULL) vars where machine in ('XXX23-4-XX','XXX23-42-XX')
order by machine,ts desc
) X WHERE X.MACHINE in ('XXX23-4-XX','XXX23-42-XX')
)Y

) W where act_in_sec >=0  order by start_time desc