zer*_*rmy 0 mysql sql postgresql
我有这个问题:
DROP TABLE IF EXISTS tmp_table;
CREATE TEMPORARY TABLE tmp_table(id int primary key)
IGNORE (
SELECT user2role.userid AS userid
FROM user2role
INNER JOIN users ON users.id=user2role.userid
INNER JOIN role ON role.roleid=user2role.roleid
WHERE role.parentrole like 'H1::H2::H3::H4::H5::%')
UNION (
SELECT groupid
FROM groups
WHERE groupid IN (2,3,4));
Run Code Online (Sandbox Code Playgroud)
此查询最初是用MySQL编写的,而不是使用DROP TABLE IF EXISTS它IF NOT EXISTS.我改变了这一部分,但我不知道该怎么办IGNORE.
首先,正在IGNORE做什么?
我试图寻找PostgreSQL等价物,但它们似乎都涉及复杂的程序.我必须为此编写程序吗?如果我必须写一个,它会是什么样子?我可以IGNORE使用一些PHP代码来模拟吗?(SQL查询由PHP生成.)
你会在postgres中这样写.
IGNORE在这里是无关紧要的,因为该表刚刚被重新创建并且保证是空的.并UNION保证不会插入重复的行.
DROP TABLE IF EXISTS tmp_table;
CREATE TEMP TABLE tmp_table(id int4 primary key);
INSERT INTO tmp_table
SELECT user2role.userid::int4 AS id
FROM user2role
JOIN users ON users.id = user2role.userid
JOIN role ON role.roleid = user2role.roleid
WHERE role.parentrole like 'H1::H2::H3::H4::H5::%'
UNION
SELECT groupid::int4
FROM groups
WHERE groupid in (2,3,4);
Run Code Online (Sandbox Code Playgroud)
如果SELECT中没有重复项,您可能会考虑更快UNION ALL而不是UNION.否则你需要UNION消除可能的欺骗.阅读这里.
如果数据集很大,可以考虑在INSERT 之后创建主键.那更快.
阅读关于效果的mySQL文档IGNORE.
在重新访问页面时,我意识到你IF NOT EXISTS在原始代码中提到了.你没有这么说,但只有原始代码只有在它不存在的情况下创建表才有意义,这就引入了它在INSERT之前不为空的可能性.在这种情况下IGNORE是相关的,需要PostgreSQL中的等价物.
所以这里是对你的问题的解释的替代答案.
CREATE TEMP TABLE IF NOT EXISTS已在PostgreSQL 9.1中实现.
对于旧版本,我最近在SO上发布了一个解决方案.
CREATE TEMP TABLE IF NOT EXISTS tmp_table(id int4 primary key);
INSERT INTO tmp_table
SELECT x.id
FROM (
SELECT user2role.userid::int4 AS id
FROM user2role
JOIN users ON users.id = user2role.userid
JOIN role ON role.roleid = user2role.roleid
WHERE role.parentrole like 'H1::H2::H3::H4::H5::%'
UNION
SELECT groupid::int4
FROM groups
WHERE groupid in (2,3,4)
) x
LEFT JOIN tmp_table t USING (id)
WHERE t.id IS NULL;
Run Code Online (Sandbox Code Playgroud)
LEFT JOIN ... WHERE t.id IS NULL排除id可能已存在的任何内容tmp_table.UNION进入子选择,因此该子句只需要应用一次.应该是最快的.
更多关于LEFT JOIN的信息.
| 归档时间: |
|
| 查看次数: |
1053 次 |
| 最近记录: |