假设有一个只有两列的表(示例如下所示)。每个'1'条目应遵循(按下面给出的排序顺序)'0'。但是,正如您所看到的,在表中,有一些“孤儿”,其中有两个连续的'1'。
如何创建一个返回所有行的查询,除了连续的'1'中的第一行? (这会将下面的例子从16行减少到14)
1 E
0 A
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
我将尝试澄清我的问题,我认为上面我简化了太多。想象一下名为logs
的一个表,有四列:
user
(包含用户名的字符串)machine
(唯一标识各种PC的字符串)type
(事件的类型:1表示日志 i n,0表示日志 o ut)time
(记录事件的时间)[机器/时间对提供唯一的密钥,因为在同一时刻没有机器可以登录或退出两次。据推测,如果需要,可以根据机器/时间排序人工创建“ID”列。]
这个想法是每个登录事件都应该伴随注销事件。理想的说法是将登录与登出相匹配相当容易,因此可以分析登录所花费的时间。
但是,在停电的情况下,不会记录注销。因此(只考虑一台机器的数据,按时间排序)如果连续有两个登录事件,我们要忽略第一次登录,因为我们没有任何可靠的数据。这是我试图解决的问题。
答案 0 :(得分: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
如果要保留double 0,请另外使用注释子句,但可能不需要。
您可能希望为数据添加自动增量列以简化此操作: Generate (i.e. write) a row number index column in MySQL
其他RDBMS(PostgreSQL,Oracle,SQL Server,..)具有row_number()
或lag()
和lead()
等窗口函数,可以更轻松地完成此类操作。
答案 1 :(得分:0)
假设您获得了一个id(添加列,在数据库中设置列ID =记录号),请使用:
select a.*
from the_table a
left join the_table b on b.id = a.id + 1
and b.col1 = 0
where a.col1 = 1
and b.id is null
答案 2 :(得分:0)
使用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
;
编辑:
对于那些不能使用CTE的穷人,很容易创建一个视图:
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
;
答案 3 :(得分:0)
尝试:
select l.*
from logs l
where l.type = 0 or
not (select type
from (select * from logs order by `time` desc) n
where n.machine = l.machine and
n.user = l.user and
n.time > l.time)
group by () )