我需要找到0到16之间缺少的数字。
我的表是这样的:
CarId FromCity_Id ToCity_Id Ran_Date RunId
1001 0 2 01-08-2013 1
1001 5 9 02-08-2013 2
1001 11 16 03-08-2013 3
1002 0 11 02-08-2013 4
1002 11 16 08-08-2013 5
我需要找出:
在now()
之后的过去三个月中,汽车尚未运行的城市之间。
例如,在上面的记录中:
总而言之,我需要生成一个查询,显示汽车在过去3个月内未运行的部分,并显示上次运行日期。
请如何进行此类查询。如果有任何存储过程,请告知。
答案 0 :(得分:2)
上帝帮助我。这使用了一个双重相关的子查询,一个可能在您的系统中不存在的表,以及过多的咖啡因。但是,嘿,它有效。
是的,到此为止。
SELECT CarId, GROUP_CONCAT(DISTINCT missing) missing
FROM MyTable r,
(SELECT @a := @a + 1 missing
FROM mysql.help_relation, (SELECT @a := -1) t
WHERE @a < 16 ) y
WHERE NOT EXISTS
(SELECT r.CarID FROM MyTable m
WHERE y.missing BETWEEN FromCity_Id AND ToCity_Id
AND r.carid = m.carid)
GROUP BY CarID;
生成(将CarID
1002的第一行更改为0-9以打开10并为我们提供更好的测试数据):
+-------+---------+
| CarId | missing |
+-------+---------+
| 1001 | 3,4,10 |
| 1002 | 10 |
+-------+---------+
2 rows in set (0.00 sec)
这一切是如何运作的?
<强>首先强> ... 内部查询为我们提供了0到16之间的数字列表:
(SELECT @a := @a + 1 missing
FROM mysql.help_relation, (SELECT @a := -1) t
WHERE @a < 16 ) y
通过从-1开始,然后在某些牺牲表中显示为该行添加1的结果。我正在使用mysql.help_relation
,因为它有超过一千行,大多数基本系统都有它。 YMMV。
然后我们与MyTable
:
SELECT CarId, ...
FROM MyTable r,
(...) y
这为我们提供了每种可能的行组合,因此我们将每个CarId和To / From ID与1-16中的每个数字混合在一起。
<强>过滤... 强>
这是它变得有趣的地方。我们需要查找不匹配数字的行,我们需要按CarID
执行此操作。这种事情会这样做(只要y.missing
存在,当我们关联子查询时就会这样):
SELECT m.CarID FROM MyTable m
WHERE y.missing BETWEEN FromCity_Id AND ToCity_Id
AND m.CarID = 1001;
请记住:y.missing
设置为1到16之间的数字,与MyTable
中的行交叉连接。这为我们提供了1-16中CarID
1001 忙碌的所有数字的列表。我们可以使用NOT EXISTS
反转该集合,当我们处理它时,将{再次)与CarId
相关联,这样我们就可以获得所有这些ID。
然后过滤不适合的行很容易:
SELECT CarId, ...
FROM MyTable r,
(...) y
WHERE NOT EXISTS
(SELECT r.CarID FROM MyTable m
WHERE y.missing BETWEEN FromCity_Id AND ToCity_Id
AND r.carid = m.carid)
<强>输出强> 为了给出一个明智的结果(尝试1),我们可以获得不同的组合。这是那个版本:
SELECT DISTINCT CarId, missing
FROM MyTable r,
(SELECT @a := @a + 1 missing
FROM mysql.help_relation, (SELECT @a := -1) t
WHERE @a < 16 ) y
WHERE NOT EXISTS
(SELECT r.CarID FROM MyTable m
WHERE y.missing BETWEEN FromCity_Id AND ToCity_Id
AND r.carid = m.carid);
这给出了:
+-------+---------+
| CarId | missing |
+-------+---------+
| 1001 | 3 |
| 1001 | 4 |
| 1001 | 10 |
| 1002 | 10 |
+-------+---------+
4 rows in set (0.01 sec)
简单添加GROUP BY
和GROUP CONCAT
可以获得您在此答案顶部获得的漂亮结果。
对于给您带来的不便,我深表歉意。
答案 1 :(得分:0)
select * from carstable where CarId not in
(select distinct CarId from ranRecordTable where DATEDIFF(NOW(), Ran_Date) <= 90)
希望这有帮助。
答案 2 :(得分:0)
这是个主意。创建所有汽车和所有号码的列表。然后,返回数据未涵盖的所有组合。这很难,因为每辆车都有不止一排。
这是一种方法:
select cars.CarId, n.n
from (select distinct CarId from t) cars cross join
(select 0 as n union all select 1 union all select 2 union all select 3 union all
select 4 union all select 5 union all select 6 union all select 7 union all
select 8 union all select 9 union all select 10 union all select 11 union all
select 12 union all select 13 union all select 14 union all select 15 union all
select 16
) n
where t.ran_date >= now() - interval 90 day and
not exists (select 1
from t t2
where t2.ran_date >= now() - interval 90 day and
t2.CarId = cars.CarId and
n.n not between t2.FromCity_id and t2.ToCity_id
);
答案 3 :(得分:0)
MySQL 5.5.32架构设置:
CREATE TABLE Table1
(`CarId` int, `FromCity_Id` int, `ToCity_Id` int, `Ran_Date` datetime, `RunId` int)
;
INSERT INTO Table1
(`CarId`, `FromCity_Id`, `ToCity_Id`, `Ran_Date`, `RunId`)
VALUES
(1001, 0, 2, '2013-08-01 00:00:00', 1),
(1001, 5, 9, '2013-08-02 00:00:00', 2),
(1001, 11, 16, '2013-08-03 00:00:00', 3),
(1002, 0, 11, '2013-08-02 00:00:00', 4),
(1002, 11, 16, '2013-08-08 00:00:00', 5)
;
查询1 :
SELECT r1.CarId,r1.ToCity_Id as Missing_From, r2.FromCity_Id as Missing_To,
max(t.Ran_Date) as Last_Run_Date
FROM (
SELECT @i1:=@i1+1 AS rownum, t.*
FROM Table1 as t, (SELECT @i1:=0) as foo
ORDER BY CarId, Ran_Date) as r1
INNER JOIN (
SELECT @i2:=@i2+1 AS rownum, t.*
FROM Table1 as t, (SELECT @i2:=0) as foo
ORDER BY CarId, Ran_Date) as r2 ON r1.CarId = r2.CarId AND
r1.ToCity_Id != r2.FromCity_Id AND
r2.rownum = (r1.rownum + 1)
INNER JOIN Table1 as t ON r1.CarId = t.CarId
WHERE r1.Ran_Date >= now() - interval 90 day
GROUP BY r1.CarId, r1.ToCity_Id, r2.FromCity_Id
<强> Results 强>:
| CARID | MISSING_FROM | MISSING_TO | LAST_RUN_DATE |
|-------|--------------|------------|-------------------------------|
| 1001 | 2 | 5 | August, 03 2013 00:00:00+0000 |
| 1001 | 9 | 11 | August, 03 2013 00:00:00+0000 |