MySQL: 检查子串序列
MySQL: Check substring sequence
我在 MySQL 中有一个 table,其中包含此字段 SERVICE,DATE_STATE,STATE:
SERVICE DATE_STATE STATE
aaaaa '2019-12-01' OK
aaaaa '2019-12-03' KO
aaaaa '2019-12-04' OK
...
xxxxx '2019-12-07' OK
xxxxx '2019-12-09' KO
记录在服务更改其状态的日期注册。
我想检查状态序列是否为 OK-KO 交替(依此类推,无限期地像 OK-KO-OK-KO-OK),当按服务分组并按日期排序时。
比如像OK-OK或KO-KO这样的序列或子序列是禁止的,我想检查和检测它们。
我不知道如何找到解决方案。
使用此查询:
SELECT service,
GROUP_CONCAT(state ORDER BY date_state) AS sequence_state
FROM T
group by service
我在一个字符串中有完整的序列 'OK,KO,OK,KO...' 但我不知道如何检查字符串中的交替。
如有任何帮助,我们将不胜感激。非常感谢
这是我的想法。尝试按州对所有偶数行进行分组。如果输出的计数大于 1,您就知道有问题。
试试这个:
SELECT IF(COUNT(*)=1, 'Clear','PROBLEM') AS CheckFlag FROM (
SELECT state FROM (
SELECT t.*
FROM (SELECT t.*, (@rn := @rn + 1) AS seqnum
FROM t CROSS JOIN
(SELECT @rn := 0) vars
) t
WHERE MOD(seqnum, 2) = 0) a
GROUP BY state
) a
不是最好的解决方案,但它会起作用!
将其用作示例数据:
CREATE TABLE services (
SERVICE varchar(50),
DATE_STATE date,
STATE varchar(2));
INSERT INTO services VALUES
("normal1", DATE("2000-01-01"), "OK"),
("normal1", DATE("2000-01-01"), "KO"),
("double ok", DATE("2000-01-01"), "OK"),
("double ok", DATE("2000-01-01"), "OK"),
("double ko", DATE("2000-01-01"), "KO"),
("double ko", DATE("2000-01-01"), "KO");
我创建了这个查询,它使用 LEAD
window 函数为您提供了所需的结果:
SELECT * FROM
(SELECT
SERVICE,
DATE_STATE,
STATE,
LEAD(STATE)
OVER (PARTITION BY SERVICE
ORDER BY DATE_STATE) AS NEXT_STATE
FROM services) AS services_with_next_state
WHERE STATE=NEXT_STATE;
在此处查看实际效果:https://www.db-fiddle.com/f/eMHRzJ6hN6xx4x2PjSLFXb/0
经过一些测试和阅读,我认为正确答案是:
- 如果您使用的是 MySQL 8.0 或更高版本,@cargo23 的回答非常有效。
- 如果你使用旧版本,一些pirouette必须这样做。经过一些测试,所有结果都符合我的预期:
SET @a :=0;
SET @b :=1;
SELECT
r.service,
r.value AS "previous state",
r2.value AS "next state",
r.date_state AS "date_state previous",
r2.date_state AS "date_state next"
FROM
(SELECT if(@a, @a:=@a+1, @a:=1) as rownum, service, state as VALUE, date_state FROM services order by service ASC, date_state asc) AS r
LEFT JOIN
(SELECT if(@b, @b:=@b+1, @b:=1) as rownum, service, state as VALUE, date_state FROM services order by service ASC, date_state asc) AS r2
ON (r.rownum+2) = r2.rownum AND r.service = r2.service
WHERE
r.value IS NOT NULL
AND r2.value IS NOT NULL
AND r.value = r2.value
ORDER BY r.service ASC, r.date_state asc;
我在 MySQL 中有一个 table,其中包含此字段 SERVICE,DATE_STATE,STATE:
SERVICE DATE_STATE STATE
aaaaa '2019-12-01' OK
aaaaa '2019-12-03' KO
aaaaa '2019-12-04' OK
...
xxxxx '2019-12-07' OK
xxxxx '2019-12-09' KO
记录在服务更改其状态的日期注册。
我想检查状态序列是否为 OK-KO 交替(依此类推,无限期地像 OK-KO-OK-KO-OK),当按服务分组并按日期排序时。 比如像OK-OK或KO-KO这样的序列或子序列是禁止的,我想检查和检测它们。
我不知道如何找到解决方案。
使用此查询:
SELECT service,
GROUP_CONCAT(state ORDER BY date_state) AS sequence_state
FROM T
group by service
我在一个字符串中有完整的序列 'OK,KO,OK,KO...' 但我不知道如何检查字符串中的交替。
如有任何帮助,我们将不胜感激。非常感谢
这是我的想法。尝试按州对所有偶数行进行分组。如果输出的计数大于 1,您就知道有问题。 试试这个:
SELECT IF(COUNT(*)=1, 'Clear','PROBLEM') AS CheckFlag FROM (
SELECT state FROM (
SELECT t.*
FROM (SELECT t.*, (@rn := @rn + 1) AS seqnum
FROM t CROSS JOIN
(SELECT @rn := 0) vars
) t
WHERE MOD(seqnum, 2) = 0) a
GROUP BY state
) a
不是最好的解决方案,但它会起作用!
将其用作示例数据:
CREATE TABLE services (
SERVICE varchar(50),
DATE_STATE date,
STATE varchar(2));
INSERT INTO services VALUES
("normal1", DATE("2000-01-01"), "OK"),
("normal1", DATE("2000-01-01"), "KO"),
("double ok", DATE("2000-01-01"), "OK"),
("double ok", DATE("2000-01-01"), "OK"),
("double ko", DATE("2000-01-01"), "KO"),
("double ko", DATE("2000-01-01"), "KO");
我创建了这个查询,它使用 LEAD
window 函数为您提供了所需的结果:
SELECT * FROM
(SELECT
SERVICE,
DATE_STATE,
STATE,
LEAD(STATE)
OVER (PARTITION BY SERVICE
ORDER BY DATE_STATE) AS NEXT_STATE
FROM services) AS services_with_next_state
WHERE STATE=NEXT_STATE;
在此处查看实际效果:https://www.db-fiddle.com/f/eMHRzJ6hN6xx4x2PjSLFXb/0
经过一些测试和阅读,我认为正确答案是:
- 如果您使用的是 MySQL 8.0 或更高版本,@cargo23 的回答非常有效。
- 如果你使用旧版本,一些pirouette必须这样做。经过一些测试,所有结果都符合我的预期:
SET @a :=0;
SET @b :=1;
SELECT
r.service,
r.value AS "previous state",
r2.value AS "next state",
r.date_state AS "date_state previous",
r2.date_state AS "date_state next"
FROM
(SELECT if(@a, @a:=@a+1, @a:=1) as rownum, service, state as VALUE, date_state FROM services order by service ASC, date_state asc) AS r
LEFT JOIN
(SELECT if(@b, @b:=@b+1, @b:=1) as rownum, service, state as VALUE, date_state FROM services order by service ASC, date_state asc) AS r2
ON (r.rownum+2) = r2.rownum AND r.service = r2.service
WHERE
r.value IS NOT NULL
AND r2.value IS NOT NULL
AND r.value = r2.value
ORDER BY r.service ASC, r.date_state asc;