WITH
声明来代替常规表,以进行调试。 我查看了CREATE TABLE的文档,并说
VALUES
可以用作查询,但没有给出示例; 因此,我编写了一个简单的测试,如下所示:
DROP TABLE IF EXISTS lookup;
CREATE TEMP TABLE lookup (
key integer,
val numeric
) AS
VALUES (0,-99999), (1,100);
但是PostgreSQL(9.3)抱怨“ AS”或附近的
语法错误
我的问题是:
我该如何修正上面的陈述?
我该如何修改它以在
VALUES
中使用?#1 楼
编辑:我将原样保留原来的答案,但请注意,a_horse_with_no_name建议的以下编辑是使用VALUES创建临时表的首选方法。从某些值中进行选择,而不仅仅是创建表并将其插入其中,您可以执行以下操作:
WITH vals (k,v) AS (VALUES (0,-9999), (1, 100))
SELECT * FROM vals;
以类似的方式实际创建临时表,使用:
WITH vals (k,v) AS (VALUES (0,-9999), (1, 100))
SELECT * INTO temporary table temp_table FROM vals;
编辑:正如a_horse_with_no_name所指出的,在文档中指出
CREATE TABLE AS...
在功能上与SELECT INTO ...
类似,但前者是SELECT INTO
的超集。后者,并且在plpgslq中使用了CREATE TABLE
来为临时变量分配值,因此在这种情况下它将失败。因此,尽管以上示例对纯SQL有效,但应首选q4312079q形式。问题,这包括强制转换为值列表内的正确数据类型并使用CTE(WITH)语句。 ,CTE始终会实现。使用CTE的理由很多,但如果使用不当,则会对性能造成重大影响。但是,在很多情况下,优化围栏实际上可以提高性能,因此需要注意这一点,而不是盲目避免。评论
来自文档:“ CREATE TABLE AS在功能上类似于SELECTINTO。CREATETABLE AS是推荐的语法”
– a_horse_with_no_name
2014年12月21日在23:14
优化围栏不一定是一件坏事。因此,我已经看到许多可以调整的语句,它们可以大大提高运行速度。
– a_horse_with_no_name
19年7月19日在11:25
当然,我也做了澄清。我一直在空间环境中使用CTE。如果您的where子句带有WHERE ST_Intersects(geom,(SELECT geom FROM sometable)或WHERE ST_Intersects(geom,ST_Buffer(anothergeom,10))之类的内容,则查询计划程序通常不使用空间索引,因为geom列不再如果您在最初的CTE中创建您感兴趣的区域,则此问题就消失了,如果您想在同一查询中的多个其他表达式中使用相同的aoi,这也非常方便,这在GIS上下文中并不罕见。
–约翰·鲍威尔(John Powell)
19年7月19日在11:57
#2 楼
create table as
需要一条select语句:DROP TABLE IF EXISTS lookup;
CREATE TEMP TABLE lookup
as
select *
from (
VALUES
(0::int,-99999::numeric),
(1::int, 100::numeric)
) as t (key, value);
您也可以使用CTE重新编写此代码:
create temp table lookup
as
with t (key, value) as (
values
(0::int,-99999::numeric),
(1::int,100::numeric)
)
select * from t;
评论
感谢您的评论。由于文档中所述的原因,您的方法显然更好。尽管已经将近5年了,但我已经编辑了答案。
–约翰·鲍威尔(John Powell)
19年7月19日在10:17
#3 楼
问题是数据类型。如果删除它们,该语句将起作用:CREATE TEMP TABLE lookup
(key, val) AS
VALUES
(0, -99999),
(1, 100) ;
您可以通过强制转换第一行的值来定义类型:
CREATE TEMP TABLE lookup
(key, val) AS
VALUES
(0::bigint, -99999::int),
(1, 100) ;
#4 楼
如果您只需要在查询中使用一些值,则您实际上不需要创建表或使用CTE。您可以对其进行内联: )。例如:SELECT *
FROM (VALUES(0::INT, -99999::NUMERIC), (1, 100)) AS lookup(key, val)
产生:是常规表格,视图等),例如:
SELECT *
FROM (VALUES(0::int, -99999::numeric), (1, 100)) AS lookup(key, val)
,(VALUES('Red'), ('White'), ('Blue')) AS colors(color);
产生以下结果:
评论
可以,但是问题是“如何使用...创建临时表?”
–超立方体ᵀᴹ
17-10-20在17:51
是的,但是为什么您需要一个带有一些固定查找值的临时表,如果不将其连接到另一个关系上呢?无论问题的措辞如何,此解决方案都会解决问题本身。
–isapir
17-10-20在18:37
也许OP只是碰巧将示例简化为一个易于发布的问题,但实际数据具有数千个值?
–stantanus
18年1月25日在20:56
OP特别使用值声明,因此我的答案仍然适用,因为这正是它的作用
–isapir
19-10-10在15:26
#5 楼
首先,始终使用标准化的CREATE TABLE AS
,如其他答案中所建议的SELECT INTO
十多年来已弃用该语法。您可以将CREATE TABLE AS
与CTE一起使用尽管这里有许多答案建议使用CTE,但这不是可取的。实际上,它可能会稍微慢一些。只需将它包装成一个表即可。 />
DROP TABLE IF EXISTS lookup;
CREATE TEMP TABLE lookup(key, value) AS
VALUES
(0::int,-99999::numeric),
(1,100);
PostgreSQL中的CTE强制实现。这是一个优化围栏。因此,通常不要在任何地方使用它们,除非您了解成本并知道可以提高性能。您可以在这里看到速度变慢,例如,
CREATE TEMP TABLE lookup(key, value) AS
SELECT key::int, value::numeric
FROM ( VALUES
(0::int,-99999::numeric),
(1,100)
) AS t(key, value);
评论
我已经更新了答案以反映标准,并指出接受的答案并不总是等同于CREATE TABLE AS,并在优化围栏上添加了注释,这是提出的一个很好的观点。 CTE具有许多优点,但是,如果盲目使用,确实会导致糟糕的性能。
–约翰·鲍威尔(John Powell)
19年7月19日在11:20
#6 楼
WITH u AS (
SELECT * FROM (VALUES (1, 'one'), (2, 'two'), (3, 'three')) AS account (id,name)
)
SELECT id, name, length(name) from u;
评论
我试图用一些更现代的建议来回答这个问题(由于选择的答案是使用不赞成使用的非标准化语法)dba.stackexchange.com/a/201575/2639