在寻找,可以转换的以下信息中的表中的单个查询

name:time    :state
a   :10:00 AM:login
b   :10:05 AM:login
a   :10:06 AM:chatting
a   :10:08 AM:Idle
b   :10:11 AM:chatting
a   :10:10 AM:Logout
b   :10:12 AM:Logout

要像这样(给定的时间范围10:00至10:15 AM作为所述查询周期)

name: State    :Duration
a   : chatting :2 Minutes 
a   : Idle     :2 Minutes
b   : chatting :1 Minute

可以这样只能用SQL做了什么?正在使用的Informix 11.5版

有帮助吗?

解决方案

它可以在一个SQL语句来完成。这里的证明。

设置

CREATE TEMP TABLE eventtable
(
    name CHAR(3) NOT NULL,
    time DATETIME HOUR TO MINUTE NOT NULL,
    state CHAR(8) NOT NULL
);

INSERT INTO eventtable(name, time, state) VALUES('a', '10:00', 'login');
INSERT INTO eventtable(name, time, state) VALUES('b', '10:05', 'login');
INSERT INTO eventtable(name, time, state) VALUES('a', '10:06', 'chatting');
INSERT INTO eventtable(name, time, state) VALUES('a', '10:08', 'Idle');
INSERT INTO eventtable(name, time, state) VALUES('b', '10:11', 'chatting');
INSERT INTO eventtable(name, time, state) VALUES('a', '10:10', 'Logout');
INSERT INTO eventtable(name, time, state) VALUES('b', '10:12', 'Logout');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:01', 'login');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:02', 'chatting');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:03', 'Idle');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:04', 'Logout');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:05', 'Idle');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:06', 'Logout');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:07', 'Idle');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:08', 'Logout');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:09', 'login');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:11', 'chatting');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:12', 'Idle');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:13', 'chatting');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:14', 'Idle');
INSERT INTO eventtable(name, time, state) VALUES('c', '10:15', 'Logout');

正确查询

请注意条件。结果表必须排除的登录'和第一其他事件之间的时间间隔;进一步,必须排除“退出”和下一个事件(大概一个“登录”)之间的时间段。信中的名称列的表之间和自联接,则非对称的时间加入柱(用“<”)确保了事件在时间顺序。该NOT EXISTS,只有相邻的事件被认为是子选择保证。在子查询中使用之间,一个错误,因为它包括了终点,这是至关重要的r1.timer2.time从范围之外;我花了几分钟的时间来发现这个bug(查询运行,但没有行返回,但是的为什么的?)!

SELECT r1.name, r1.state, r2.TIME - r1.TIME AS duration
    FROM eventtable r1, eventtable r2
    WHERE r1.name = r2.name
      AND r1.time < r2.time
      AND r1.state != 'login'
      AND r1.state != 'Logout'
      AND r1.time BETWEEN DATETIME(10:00) HOUR TO MINUTE
                      AND DATETIME(10:15) HOUR TO MINUTE
      AND r2.time BETWEEN DATETIME(10:00) HOUR TO MINUTE
                      AND DATETIME(10:15) HOUR TO MINUTE
      AND NOT EXISTS (SELECT 1 FROM eventtable r3
                            WHERE r3.time > r1.time AND r3.time < r2.time
                      AND r3.name = r1.name
                      AND r3.name = r2.name);

这产生了答案:

name state      duration
a    chatting   0:02
a    Idle       0:02
b    chatting   0:01

c    chatting   0:01
c    Idle       0:01
c    Idle       0:01
c    Idle       0:01
c    chatting   0:01
c    Idle       0:01
c    chatting   0:01
c    Idle       0:01

在“持续时间”的值是一个INTERVAL小时到分钟;如果想在短短几分钟内的值,则必须将其用铸造转换(使用4为精密以允许间隔达到1440分钟,或1天;数据是模糊的更长的时间帧):

(r2.time - r1.time)::INTERVAL MINUTE(4) TO MINUTE

或者:

CAST (r2.time - r1.time AS INTERVAL MINUTE(4) TO MINUTE)

IBM的Informix动态服务器(IDS)具有用于时间常数非常详细的符号。在标准SQL中,你可以使用时间作为类型和时间'10:00:作为一个值00' ,但会秒严格标准SQL是必要的。 IDS确实提供人们想要确切类型 - 比如DATETIME小时到分钟。您还会写在标准SQL INTERVAL MINUTE(4);该 'TO MINUTE' 应该是可选的。

不正确的查询

在我的雷陶菲克的回答评论,我指出,EXISTS子查询是必要的,以确保所考虑的事件是连续的 - 不存在居间事件。下面是与添加到输出开始和结束时间相同的查询,并且EXISTS子句缺失(和“持续时间”重命名为“失效”):

SELECT r1.name, r1.state, r2.TIME - r1.TIME AS lapse,
       r1.time AS start, r2.time AS end
    FROM eventtable r1, eventtable r2
    WHERE r1.name = r2.name
      AND r1.time < r2.time
      AND r1.state != 'login'
      AND r1.state != 'Logout'
      AND r1.time BETWEEN DATETIME(10:00) HOUR TO MINUTE
                      AND DATETIME(10:15) HOUR TO MINUTE
      AND r2.time BETWEEN DATETIME(10:00) HOUR TO MINUTE
                      AND DATETIME(10:15) HOUR TO MINUTE;

这产生了答案:

name state     lapse start end
a    chatting   0:04 10:06 10:10
a    chatting   0:02 10:06 10:08
a    Idle       0:02 10:08 10:10
b    chatting   0:01 10:11 10:12
c    chatting   0:13 10:02 10:15
c    chatting   0:12 10:02 10:14
c    chatting   0:11 10:02 10:13
c    chatting   0:10 10:02 10:12
c    chatting   0:09 10:02 10:11
c    chatting   0:07 10:02 10:09
c    chatting   0:06 10:02 10:08
c    chatting   0:05 10:02 10:07
c    chatting   0:04 10:02 10:06
c    chatting   0:03 10:02 10:05
c    chatting   0:02 10:02 10:04
c    chatting   0:01 10:02 10:03
c    Idle       0:12 10:03 10:15
c    Idle       0:11 10:03 10:14
c    Idle       0:10 10:03 10:13
c    Idle       0:09 10:03 10:12
c    Idle       0:08 10:03 10:11
c    Idle       0:06 10:03 10:09
c    Idle       0:05 10:03 10:08
c    Idle       0:04 10:03 10:07
c    Idle       0:03 10:03 10:06
c    Idle       0:02 10:03 10:05
c    Idle       0:01 10:03 10:04
c    Idle       0:10 10:05 10:15
c    Idle       0:09 10:05 10:14
c    Idle       0:08 10:05 10:13
c    Idle       0:07 10:05 10:12
c    Idle       0:06 10:05 10:11
c    Idle       0:04 10:05 10:09
c    Idle       0:03 10:05 10:08
c    Idle       0:02 10:05 10:07
c    Idle       0:01 10:05 10:06
c    Idle       0:08 10:07 10:15
c    Idle       0:07 10:07 10:14
c    Idle       0:06 10:07 10:13
c    Idle       0:05 10:07 10:12
c    Idle       0:04 10:07 10:11
c    Idle       0:02 10:07 10:09
c    Idle       0:01 10:07 10:08
c    chatting   0:04 10:11 10:15
c    chatting   0:03 10:11 10:14
c    chatting   0:02 10:11 10:13
c    chatting   0:01 10:11 10:12
c    Idle       0:03 10:12 10:15
c    Idle       0:02 10:12 10:14
c    Idle       0:01 10:12 10:13
c    chatting   0:02 10:13 10:15
c    chatting   0:01 10:13 10:14
c    Idle       0:01 10:14 10:15

这示出了如何对用户“c”的每个有资格的起始行与每个有资格的结束行匹配时,给出数据的许多虚假的行。该NOT EXISTS子查询是一个共同的主题,基于时间的查询的时候。你可以找到关于这些操作的信息,斯诺德格拉斯的“发展在SQL <面向时间的应用程序/一> “(PDF可在线URL),以及日期,达尔文和Lorentzos” 时空数据和关系模型”。

其他提示

我敢肯定它可以只使用SQL来完成,它会带我相当多的时间来为你的查询,我会当我做过编辑。我认为基本的步骤首先是由子句总和来计算的时候每一个需要的量(以每个条目,并将其加入到下一个条目,并减去找时间差做),那么一个简单的组将轻松搞定它到表单你所描述。

编辑:这是我想出了

SELECT l.userid, l.state, SUM(t.minutes) AS duration
FROM Log l 
INNER JOIN (
    SELECT l1.id, (l2.time - l1.time) AS minutes
    FROM Log l1, Log l2
    WHERE l2.time == ( 
        -- find the next entry --
        SELECT TOP 1 ls.time
        FROM Log ls
        WHERE ls.Time > l1.Time && ls.userid = l1.userid
        ORDER BY ls.Time
    )
) t ON l.id == t.id
GROUP BY l.userid, l.state
ORDER BY l.userid

这是半伪代码,我做了所有的表名和事情,你将不能够只从另一个减去一个时间,你可能会使用DATEDIFF函数。此外,虽然,我认为这是它的要点。我认为SQL是最惊人的语言之一,你几乎可以做一点事情的代码。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top