Mysql 筛选出孤立表项
假设有一个只有两列的表(下面显示了一个示例)。每个“1”条目后面都应该跟一个“0”(按照下面给出的排序顺序)。但是,正如您所看到的,在表中,有一些“孤儿”,其中有两个连续的“1” 如何创建一个返回所有行的查询,除了任何连续“1”中的第一行之外?(这将使下面的示例从16行减少到14行)Mysql 筛选出孤立表项,mysql,sql,duplicate-removal,gaps-and-islands,Mysql,Sql,Duplicate Removal,Gaps And Islands,假设有一个只有两列的表(下面显示了一个示例)。每个“1”条目后面都应该跟一个“0”(按照下面给出的排序顺序)。但是,正如您所看到的,在表中,有一些“孤儿”,其中有两个连续的“1” 如何创建一个返回所有行的查询,除了任何连续“1”中的第一行之外?(这将使下面的示例从16行减少到14行) 我将尝试澄清我的问题,我认为上面我简化了太多。想象一个名为“日志”的表,它有四列: user(包含用户名的字符串) 机器(唯一标识各种PC的字符串) 类型(事件类型:1表示登录,0表示注销) 时间(记录事件的时
我将尝试澄清我的问题,我认为上面我简化了太多。想象一个名为“日志”的表,它有四列:
(包含用户名的字符串)user
(唯一标识各种PC的字符串)机器
(事件类型:1表示登录,0表示注销)类型
(记录事件的时间)时间
- 只有1是被复制的,而不是0
- 如果有更多的1,你想去掉所有的前1
SELECT x.*
FROM x
LEFT JOIN x y on y.id = (x.id + 1)
WHERE (x.nr = y.nr) IS NOT TRUE -- OR x.nr = 0
ORDER BY x.id
如果要保留双0,请另外使用注释子句,但可能不需要
问题编辑后编辑:
您可能希望向数据中添加一个自动增量列,以简化此操作:
其他RDBMS(PostgreSQL、Oracle、SQL Server等)具有窗口功能,如row_number()
或lag()
和lead()
- 只有1是被复制的,而不是0
- 如果有更多的1,你想去掉所有的前1
你的文字上写着“除了连续的第一个”,但我想,这就是你想要的。或者只有2个,那么它是一样的
SELECT x.*
FROM x
LEFT JOIN x y on y.id = (x.id + 1)
WHERE (x.nr = y.nr) IS NOT TRUE -- OR x.nr = 0
ORDER BY x.id
如果要保留双0,请另外使用注释子句,但可能不需要
问题编辑后编辑:
您可能希望向数据中添加一个自动增量列,以简化此操作:
其他RDBMS(PostgreSQL、Oracle、SQL Server等)具有窗口功能,如行号()
或滞后()
和超前()
,这使得此类操作更加容易。使用CTE将滞后逻辑与选择标准分离
DROP TABLE tmp.bits;
CREATE TABLE tmp.bits
( id SERIAL NOT NULL
, bit INTEGER NOT NULL
, code CHAR(1)
);
INSERT INTO tmp.bits(bit, code) VALUES
(1, 'T' )
, (0, 'S' )
, (1, 'R' )
, (0, 'E' )
, (1, 'F' )
, (0, 'T' )
, (1, 'G' )
, (1, 'T' )
, (0, 'R' )
, (1, 'X' )
, (1, 'R' )
, (0, 'R' )
, (1, 'E' )
, (0, 'T' )
;
SET search_path='tmp';
SELECT * FROM bits;
-- EXPLAIN ANALYZE
WITH prevnext AS (
SELECT
bt.id AS thisid
, bt.bit AS thisbit
, bt.code AS thiscode
, bp.bit AS prevbit
, bp.code AS prevcode
FROM bits bt
LEFT JOIN bits bp ON (bt.id > bp.id)
AND NOT EXISTS ( SELECT * FROM bits nx
WHERE nx.id > bp.id
AND nx.id < bt.id
)
)
SELECT thisid, thisbit, thiscode
FROM prevnext
WHERE thisbit=0
OR prevbit IS NULL OR thisbit <> prevbit
;
删除表tmp.bits;
创建表tmp.bits
(id序列号不为空
,位整数不为空
,代码字符(1)
);
插入tmp.bits(位,代码)值
(1,‘T’)
,(0,'S')
,(1,'R')
,(0,'E')
,(1,'F')
,(0,'T')
,(1,'G')
,(1,‘T’)
,(0,'R')
,(1,'X')
,(1,'R')
,(0,'R')
,(1,'E')
,(0,'T')
;
设置search_path='tmp';
从位中选择*;
--解释分析
以下一个为例(
挑选
bt.id作为thisid
,bt.bit与thisbit相同
,bt.code作为此代码
,bp.bit作为前一位
,bp.code作为prevcode
来自英国电信
左连接位bp开启(bt.id>bp.id)
并且不存在(从位nx中选择*
其中nx.id>bp.id
和nx.id
编辑:
对于那些不能使用CTE的糟糕的SOAL,很容易创建一个视图:
CREATE VIEW prevnext AS (
SELECT
bt.id AS thisid
, bt.bit AS thisbit
,bt.code AS thiscode
, bp.bit AS prevbit
, bp.code AS prevcode
FROM bits bt
LEFT JOIN bits bp ON (bt.id > bp.id)
AND NOT EXISTS ( SELECT * FROM bits nx
WHERE nx.id > bp.id
AND nx.id < bt.id
)
)
;
SELECT thisid, thisbit, thiscode
FROM prevnext
WHERE thisbit=0
OR prevbit IS NULL OR thisbit <> prevbit
;
创建下一个视图作为(
挑选
bt.id作为thisid
,bt.bit与thisbit相同
,bt.code作为此代码
,bp.bit作为前一位
,bp.code作为prevcode
来自英国电信
左连接位bp开启(bt.id>bp.id)
并且不存在(从位nx中选择*
其中nx.id>bp.id
和nx.id
使用CTE将滞后逻辑与选择标准分离
DROP TABLE tmp.bits;
CREATE TABLE tmp.bits
( id SERIAL NOT NULL
, bit INTEGER NOT NULL
, code CHAR(1)
);
INSERT INTO tmp.bits(bit, code) VALUES
(1, 'T' )
, (0, 'S' )
, (1, 'R' )
, (0, 'E' )
, (1, 'F' )
, (0, 'T' )
, (1, 'G' )
, (1, 'T' )
, (0, 'R' )
, (1, 'X' )
, (1, 'R' )
, (0, 'R' )
, (1, 'E' )
, (0, 'T' )
;
SET search_path='tmp';
SELECT * FROM bits;
-- EXPLAIN ANALYZE
WITH prevnext AS (
SELECT
bt.id AS thisid
, bt.bit AS thisbit
, bt.code AS thiscode
, bp.bit AS prevbit
, bp.code AS prevcode
FROM bits bt
LEFT JOIN bits bp ON (bt.id > bp.id)
AND NOT EXISTS ( SELECT * FROM bits nx
WHERE nx.id > bp.id
AND nx.id < bt.id
)
)
SELECT thisid, thisbit, thiscode
FROM prevnext
WHERE thisbit=0
OR prevbit IS NULL OR thisbit <> prevbit
;
删除表tmp.bits;
创建表tmp.bits
(id序列号不为空
,位整数不为空
,代码字符(1)
);
插入tmp.bits(位,代码)值
(1,‘T’)
,(0,'S')
,(1,'R')
,(0,'E')
,(1,'F')
,(0,'T')
,(1,'G')
,(1,‘T’)
,(0,'R')
,(1,'X')
,(1,'R')
,(0,'R')
,(1,'E')
,(0,'T')
;
设置search_path='tmp';
从位中选择*;
--解释分析
以下一个为例(
挑选
bt.id作为thisid
,bt.bit与thisbit相同
,bt.code作为此代码
,bp.bit作为前一位
,bp.code作为prevcode
来自英国电信
左连接位bp开启(bt.id>bp.id)
并且不存在(从位nx中选择*
其中nx.id>bp.id
和nx.id
编辑:
对于那些不能使用CTE的糟糕的SOAL,很容易创建一个视图:
CREATE VIEW prevnext AS (
SELECT
bt.id AS thisid
, bt.bit AS thisbit
,bt.code AS thiscode
, bp.bit AS prevbit
, bp.code AS prevcode
FROM bits bt
LEFT JOIN bits bp ON (bt.id > bp.id)
AND NOT EXISTS ( SELECT * FROM bits nx
WHERE nx.id > bp.id
AND nx.id < bt.id
)
)
;
SELECT thisid, thisbit, thiscode
FROM prevnext
WHERE thisbit=0
OR prevbit IS NULL OR thisbit <> prevbit
;
创建下一个视图作为(
挑选
bt.id作为thisid
,bt.bit与thisbit相同
,bt.code作为此代码
,bp.bit作为前一位
,bp.code作为prevcode
来自英国电信
左连接位bp开启(bt.id>bp.id)
并且不存在(从位nx中选择*
其中nx.id>bp.id
和nx.id