如何解决插入表中,这样它就不会创建连续的重复项H2
我需要为H2 db创建插入查询。我需要在表中插入,这样它就不会在表中创建连续的重复项并忽略它。例如,
First name | Last name | Date
A | Z | 2018-12-02
B | Y | 2018-12-03
A | X | 2018-12-04
如果我必须插入行`| A | W |上表中的2018-12-01按日期升序排列,它检查“名字”列中的连续重复项。由于它会在表中创建连续的重复项,因此将其忽略。
First name | Last name | Date
A | W | 2018-12-01
A | Z | 2018-12-02
B | Y | 2018-12-03
A | X | 2018-12-04
解决方法
在H2中,您可以使用以下SQL:
INSERT INTO tableName SELECT * FROM VALUES ('A','W',DATE '2018-12-01') T(F,L,D)
WHERE NOT EXISTS (
SELECT * FROM tableName
QUALIFY "First name" = F
AND DENSE_RANK() OVER (ORDER BY "Date")
- DENSE_RANK(D) WITHIN GROUP (ORDER BY "Date") OVER() IN (-1,0)
);
此处使用假设集DENSE_RANK
函数的窗口版本(不要将其与窗口DENSE_RANK
函数混合使用,这是另一种),用于确定新行的插入位置:>
DENSE_RANK(D) WITHIN GROUP (ORDER BY "Date") OVER()
此聚合函数是SQL标准的一部分,但在SQL标准中,可能不会用作窗口函数,但对H2的限制较少。
然后,普通的DENSE_RANK
窗口函数用于为表中的现有行编号。对于插入行之前的行,行数与假设行的数量之间的差为-1,而对于插入行之后的行,则为0。
我们只需要检查具有相同"First name"
值的行。因此整个过滤条件将是
"First name" = F
AND DENSE_RANK() OVER (ORDER BY "Date")
- DENSE_RANK(D) WITHIN GROUP (ORDER BY "Date") OVER() IN (-1,0)
在SQL标准中,您无法在评估窗口函数之后过滤结果,但是H2为此目的具有非标准的QUALIFY
子句(来自Teradata),在其他DBMS中需要子查询。
决定是否可以插入行的最终条件是
WHERE NOT EXISTS (
SELECT * FROM tableName
QUALIFY "First name" = F
AND DENSE_RANK() OVER (ORDER BY "Date")
- DENSE_RANK(D) WITHIN GROUP (ORDER BY "Date") OVER() (-1,0)
);
如果没有这样的行,则插入新行将不会创建两个具有相同"First name"
值的连续行。
可以在select命令的普通标准插入中使用此条件。
如果表具有许多行,则预计此解决方案不会很快。一种更有效的解决方案可以使用子查询来查找上一行和下一行,例如NOT EXISTS SELECT * FROM (SELECT * FROM tableName WHERE "Date" > D ORDER BY "Date" FETCH FIRST ROW ONLY) UNION (SELECT * FROM tableName WHERE "Date" < D ORDER BY "Date" DESC FETCH FIRST ROW ONLY) WHERE "First name" = F
,但是H2不允许引用深度嵌套查询中的外部表,因此这里的D
需要用JDBC替换。参数(… VALUES (?1,?2,?3) … WHERE "Date" < ?3 …
)。您可以尝试自己构建这样的命令。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。