在运行时在sql数据库中过滤出重复值-基于set
我有一个数据库问题,目前无法通过简单的解决方案来解决。在我的数据库中,我有一个表来存储事件值。带有时间戳的0和1. 问题是,同一事件有可能作为业务规则发生两次。像下面
- '2008-09-22 16:28:14.133',0
- '2008-09-22 16:28:35.233',1
- '2008-09-22 16:29:16.353',1
- '2008-09-22 16:31:37.273',0
- '2008-09-22 16:35:43.134',0
- '2008-09-22 16:36:39.633',1
- '2008-09-22 16:41:40.733',0
在现实生活中,这些事件是循环的,我试图查询以获取这些事件的循环,但是我需要忽略重复的值(1,1),当前的解决方案是使用SQL游标来循环每个值,如果以前是一样的。香港专业教育学院考虑在触发器上使用触发器来清理后处理表中,但我不能想到一个简单的解决方案基于此设置。
有什么想法或者建议吗?
谢谢
解决方案
(前言.......我只在oracle中完成了此操作,但是我很确定数据库是否支持触发器是有可能的)
有一个插入前触发器,用于选择具有最大时间戳值的行。如果该行的值与我们要插入的行的值相同,则将其忽略。
这应该使它们都处于正确的状态。
现在,如果我们需要同时存储两组状态,则触发器可以始终插入全包表中,但是仅当值更改时才执行查找并插入"已过滤"表中。
以便我了解问题。
如果我们根据时间戳对行集进行排序,有时会出现重复的值,例如上面第二对和第三项中的一对1?然后在第4个和第5个中有双0,是吗?
我们是否想要对应对中的最后一个(如果有两个以上,则为序列)?
为什么需要删除它们?我之所以问是因为,除非它们占据该表的很大一部分,否则当我们需要处理或者显示它们时,就像按顺序进行操作一样,将它们过滤掉可能会更容易。
一个解决方案虽然不是很好,但是将获取高于我们正在检查的当前行的时间戳的最小时间戳,然后从中获取值,如果相同,则不返回当前行。
这是获取所有内容的SQL:
SELECT timestamp, value FROM yourtable
以下是加入以获得当前时间戳以上的最小时间戳的方法:
SELECT T1.timestamp, MIN(T2.timestamp) AS next_timestamp, T1.value FROM yourtable T1, yourtable T2 WHERE T2.timestamp > T1.timestamp GROUP BY T1.timestamp, T1.value
(我担心上面的查询会非常慢)
然后检索与该最小时间戳相对应的值
SELECT T3.timestamp, T3.value FROM ( SELECT T1.timestamp, MIN(T2.timestamp) AS next_timestamp, T1.value FROM yourtable T1, yourtable T2 WHERE T2.timestamp > T1.timestamp GROUP BY T1.timestamp, T1.value ) T3, yourtable AS T4 WHERE T3.next_timestamp = T4.timestamp AND T3.value <> T4.value
不幸的是,这并不会产生最后的值,因为它需要一个后续值进行比较。一个简单的伪哨兵值(我们可以在需要时将其并入)将处理该问题。
这是我针对上述查询测试的sqlite数据库转储:
BEGIN TRANSACTION; CREATE TABLE yourtable (timestamp datetime, value int); INSERT INTO "yourtable" VALUES('2008-09-22 16:28:14.133',0); INSERT INTO "yourtable" VALUES('2008-09-22 16:28:35.233',1); INSERT INTO "yourtable" VALUES('2008-09-22 16:29:16.353',1); INSERT INTO "yourtable" VALUES('2008-09-22 16:31:37.273',0); INSERT INTO "yourtable" VALUES('2008-09-22 16:35:43.134',0); INSERT INTO "yourtable" VALUES('2008-09-22 16:36:39.633',1); INSERT INTO "yourtable" VALUES('2008-09-22 16:41:40.733',0); INSERT INTO "yourtable" VALUES('2099-12-31 23:59:59.999',2); COMMIT;
这是(格式化的)输出:
timestamp value 2008-09-22 16:28:14.133 0 2008-09-22 16:29:16.353 1 2008-09-22 16:35:43.134 0 2008-09-22 16:36:39.633 1 2008-09-22 16:41:40.733 0
这个问题实际上是一个数据捕获问题。典型的数据库引擎不是解决它的好选择。一个简单的预处理器应该检测输入数据集中的变化,并仅存储相关数据(时间戳等)。
一个简单的解决方案是在数据库环境中(例如在Oracle中)创建一个程序包,该程序包可以具有用于存储最后输入数据集的本地内存变量,并消除不必要的数据库访问。
当然,我们可以使用数据库环境的所有功能来定义"输入数据集的更改"并存储过滤后的数据。因此,随心所欲可能很容易,也可能很复杂。
它使用SQL Server公用表表达式,但可以内联,表t的列为dt和cyclestate:
;WITH Firsts AS ( SELECT t1.dt ,MIN(t2.dt) AS Prevdt FROM t AS t1 INNER JOIN t AS t2 ON t1.dt < t2.dt AND t2.cyclestate <> t1.cyclestate GROUP BY t1.dt ) SELECT MIN(t1.dt) AS dt_start ,t2.dt AS dt_end FROM t AS t1 INNER JOIN Firsts ON t1.dt = Firsts.dt INNER JOIN t AS t2 ON t2.dt = Firsts.Prevdt AND t1.cyclestate <> t2.cyclestate GROUP BY t2.dt ,t2.cyclestate HAVING MIN(t1.cyclestate) = 0