我想找到一种方法在 1 mysql 查询中获得适当的结果
I want to to find a way to get my appropriate result in 1 mysql query
我有一个 table 名称 order_history
,我在其中存储了 old_status
和 new_status
公司订单。
table 的架构:
CREATE TABLE order_history (
id int(11) NOT NULL AUTO_INCREMENT,
old_status longtext COLLATE utf8_unicode_ci,
new_status longtext COLLATE utf8_unicode_ci,
created_at datetime NOT NULL,
order_id int(11) DEFAULT NULL,
PRIMARY KEY (id)
}
要填充的插入是:
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (1, '56', '714', '2020-12-20 21:37:54', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (2, '714', '61', '2020-12-20 21:37:56', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (3, '61', '713', '2020-12-20 21:38:17', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (4, '713', '42', '2020-12-20 21:38:26', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (5, '42', '51', '2020-12-20 21:59:17', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (6, '56', '714', '2020-12-20 22:21:27', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (7, '714', '61', '2020-12-20 22:21:29', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (8, '61', '713', '2020-12-20 22:24:28', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (9, '713', '42', '2020-12-20 22:24:43', 94471496);
现在的问题是我想在 new_status=61
行和 new_status=42 and old_status=713
行之间找到 created_at
的 TIMEDIFF
。
所以在这个例子中,受影响的行应该是 (2,4,7,9) ,正确的答案将是 TIMEDIFF
ids (2,4) 行和 ids ( 7,9).但是我的查询 returns 3 结果而不是 2 并且它还计算行 (2,9) 之间的 TIMEDIFF
。
我怎样才能排除这个结果?
这是我的查询:
select *
from (select oschStart.order_id as order_id, TIMEDIFF(oschEnd.created_at, oschStart.created_at) as confirm_time
from (select osch1.order_id, osch1.created_at
from order_history osch1
where osch1.old_status = 713
and osch1.new_status = 42
) oschEnd
join (select osch1.order_id, osch1.created_at
from order_history osch1
where osch1.new_status = 61
) oschStart
on oschStart.order_id = oschEnd.order_id and oschEnd.created_at > oschStart.created_at) order_time;
更简单的方法是使用相关子查询
select *,
timediff(
(select created_at from order_history oh1
where oh1.order_id = oh.order_id and
oh1.id > oh.id and
oh1.old_status = '713' and oh1.new_status = '42'
order by oh1.id asc limit 1),oh.created_at) diff
from order_history oh
where new_status = 61;
为什么你有不想要的结果?
oschStart
将产生行 [2,7],oschEnd
将产生行 [4,9]。加入这些子查询将产生 4 行 [(2,4),(2,9),(7,4),(7,9)]。您的条件 (on oschStart.order_id = oschEnd.order_id and oschEnd.created_at > oschStart.created_at
) 将产生以下三行:[(2,4),(2,9),(7,9)]。它不会修剪 (2,9),因为 9[created_date
] > 2[created_date
]。因此,您的查询将匹配 oschStart
及其后出现的所有 oschEnd
。但是你需要它与第一个出现的 oschEnd
相匹配
解决方案
使用group by
。如果您按字段上的查询结果分组并将其他字段放在 select 部分,Mysql 将用该“组”的第一行填充这些字段。所以假设 order_history
在 created_date
上排序,你可以使用这个查询:
select order_time.id , order_time.*
from (
select oschStart.id as id, oschStart.order_id as order_id,
TIMEDIFF(oschEnd.created_at, oschStart.created_at) as confirm_time
from (select osch1.order_id, osch1.created_at
from order_history osch1
where osch1.old_status = 713
and osch1.new_status = 42
) oschEnd
join (select osch1.id as id, osch1.order_id, osch1.created_at
from order_history osch1
where osch1.new_status = 61
) oschStart
on oschStart.order_id = oschEnd.order_id
and oschEnd.created_at > oschStart.created_at)
order_time
group by order_time.id;
我有一个 table 名称 order_history
,我在其中存储了 old_status
和 new_status
公司订单。
table 的架构:
CREATE TABLE order_history (
id int(11) NOT NULL AUTO_INCREMENT,
old_status longtext COLLATE utf8_unicode_ci,
new_status longtext COLLATE utf8_unicode_ci,
created_at datetime NOT NULL,
order_id int(11) DEFAULT NULL,
PRIMARY KEY (id)
}
要填充的插入是:
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (1, '56', '714', '2020-12-20 21:37:54', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (2, '714', '61', '2020-12-20 21:37:56', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (3, '61', '713', '2020-12-20 21:38:17', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (4, '713', '42', '2020-12-20 21:38:26', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (5, '42', '51', '2020-12-20 21:59:17', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (6, '56', '714', '2020-12-20 22:21:27', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (7, '714', '61', '2020-12-20 22:21:29', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (8, '61', '713', '2020-12-20 22:24:28', 94471496);
INSERT INTO order_history (id, old_status, new_status, created_at, order_id) VALUES (9, '713', '42', '2020-12-20 22:24:43', 94471496);
现在的问题是我想在 new_status=61
行和 new_status=42 and old_status=713
行之间找到 created_at
的 TIMEDIFF
。
所以在这个例子中,受影响的行应该是 (2,4,7,9) ,正确的答案将是 TIMEDIFF
ids (2,4) 行和 ids ( 7,9).但是我的查询 returns 3 结果而不是 2 并且它还计算行 (2,9) 之间的 TIMEDIFF
。
我怎样才能排除这个结果?
这是我的查询:
select *
from (select oschStart.order_id as order_id, TIMEDIFF(oschEnd.created_at, oschStart.created_at) as confirm_time
from (select osch1.order_id, osch1.created_at
from order_history osch1
where osch1.old_status = 713
and osch1.new_status = 42
) oschEnd
join (select osch1.order_id, osch1.created_at
from order_history osch1
where osch1.new_status = 61
) oschStart
on oschStart.order_id = oschEnd.order_id and oschEnd.created_at > oschStart.created_at) order_time;
更简单的方法是使用相关子查询
select *,
timediff(
(select created_at from order_history oh1
where oh1.order_id = oh.order_id and
oh1.id > oh.id and
oh1.old_status = '713' and oh1.new_status = '42'
order by oh1.id asc limit 1),oh.created_at) diff
from order_history oh
where new_status = 61;
为什么你有不想要的结果?
oschStart
将产生行 [2,7],oschEnd
将产生行 [4,9]。加入这些子查询将产生 4 行 [(2,4),(2,9),(7,4),(7,9)]。您的条件 (on oschStart.order_id = oschEnd.order_id and oschEnd.created_at > oschStart.created_at
) 将产生以下三行:[(2,4),(2,9),(7,9)]。它不会修剪 (2,9),因为 9[created_date
] > 2[created_date
]。因此,您的查询将匹配 oschStart
及其后出现的所有 oschEnd
。但是你需要它与第一个出现的 oschEnd
解决方案
使用group by
。如果您按字段上的查询结果分组并将其他字段放在 select 部分,Mysql 将用该“组”的第一行填充这些字段。所以假设 order_history
在 created_date
上排序,你可以使用这个查询:
select order_time.id , order_time.*
from (
select oschStart.id as id, oschStart.order_id as order_id,
TIMEDIFF(oschEnd.created_at, oschStart.created_at) as confirm_time
from (select osch1.order_id, osch1.created_at
from order_history osch1
where osch1.old_status = 713
and osch1.new_status = 42
) oschEnd
join (select osch1.id as id, osch1.order_id, osch1.created_at
from order_history osch1
where osch1.new_status = 61
) oschStart
on oschStart.order_id = oschEnd.order_id
and oschEnd.created_at > oschStart.created_at)
order_time
group by order_time.id;