PostgreSQL에서 VALUES를 사용하여 임시 테이블을 생성하는 방법 알아 내려고 노력 중 입니다. 나는 설명서 보았다

PostgreSQL을 배우고 WITH디버깅을 위해 임시 테이블 또는 일반 테이블 대신 사용할 수 있는 선언 을 만드는 방법을 알아 내려고 노력 중 입니다.

나는 설명서 보았다 표를 작성 하고 그것을 말한다 VALUES쿼리로 사용할 수 있지만 예를주지 않는다; 그에 VALUES연결된 조항에 대한 문서도 예제가 없습니까?

그래서 다음과 같이 간단한 테스트를 작성했습니다.

DROP TABLE IF EXISTS lookup;
CREATE TEMP TABLE lookup (
  key integer,
  val numeric
) AS
VALUES (0,-99999), (1,100);

그러나 PostgreSQL (9.3)은 다음에 대해 불평하고 있습니다.

“AS”근처 또는 근처의 구문 오류

내 질문은 :

  1. 위의 진술을 어떻게 고칠 수 있습니까?

  2. 에 사용되도록 어떻게 조정할 수 WITH block있습니까?

미리 감사드립니다.



답변

편집 : 원래 허용 된 답변을 그대로두고 있지만 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에 사용되는 그 경우. 따라서 위의 예는 일반 SQL에 유효하지만 CREATE TABLE형식이 선호됩니다.

CREATE TEMP TABLE temp_table AS                                     
WITH t (k, v) AS (
 VALUES
 (0::int,-99999::numeric), 
 (1::int,100::numeric)
)
SELECT * FROM t;

또한 a_horse_with_no_name의 의견과 OP의 원래 질문에서 값 목록 내의 올바른 데이터 유형으로의 캐스트가 포함되며 CTE (WITH) 문을 사용합니다.

또한 Evan Carrol의 답변에서 지적했듯이 CTE 쿼리는 최적화 펜스입니다 . 즉, CTE는 항상 구체화됩니다. CTE를 사용하는 데는 여러 가지 이유가 있지만주의해서 사용하지 않으면 성능이 크게 저하 될 수 있습니다. 그러나 최적화 펜스가 실제로 성능을 향상시킬 수있는 경우가 많기 때문에 맹목적으로 피할 수는 없습니다.


답변

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;

답변

문제는 데이터 유형입니다. 그것들을 제거하면 진술이 작동합니다.

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) ;

답변

쿼리에 몇 가지 값을 사용하는 것만으로도 테이블을 만들거나 CTE를 사용할 필요가 없습니다. 당신은 그들을 인라인 할 수 있습니다 :

SELECT  *
FROM    (VALUES(0::INT, -99999::NUMERIC), (1, 100)) AS lookup(key, val)

그런 다음 CROSS JOIN(다른 관계는 물론 일반 테이블, 뷰 등 이 될 수있는) 직교 제품을 얻을 수 있습니다. 예 :

SELECT  *
FROM    (VALUES(0::int, -99999::numeric), (1, 100)) AS lookup(key, val)
       ,(VALUES('Red'), ('White'), ('Blue')) AS colors(color);

결과는 다음과 같습니다.

key |val    |color |
----|-------|------|
0   |-99999 |Red   |
1   |100    |Red   |
0   |-99999 |White |
1   |100    |White |
0   |-99999 |Blue  |
1   |100    |Blue  |

또는 JOIN다른 관계가있는 값 (다시 일반 테이블, 뷰 등이 될 수 있음). 예 :

SELECT  *
FROM    (VALUES(0::int, -99999::numeric), (1, 100)) AS lookup(key, val)
  JOIN  (VALUES('Red', 1), ('White', 0), ('Blue', 1)) AS colors(color, lookup_key)
          ON colors.lookup_key = lookup.key;

결과는 다음과 같습니다.

key |val    |color |lookup_key |
----|-------|------|-----------|
1   |100    |Red   |1          |
0   |-99999 |White |0          |
1   |100    |Blue  |1          |

답변

먼저 항상 표준화 사용 CREATE TABLE AS, SELECT INTO10 년 이상 사용되지 않는 구문되었습니다 다른 답변에 제안. CTE와 함께 사용할 수 있습니다CREATE TABLE AS

여기에 많은 답변이 CTE 사용을 제안하고 있지만 바람직하지 않습니다. 실제로 다소 느려질 수 있습니다. 그냥 테이블로 마무리하십시오.

DROP TABLE IF EXISTS lookup;

CREATE TEMP TABLE lookup(key, value) AS
  VALUES
  (0::int,-99999::numeric),
  (1,100);

select 문을 작성해야하는 경우에도 그렇게 할 수 있습니다 (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);

PostgreSQL의 CTE는 materialization을 강제합니다. 최적화 펜스입니다. 따라서 비용을 이해하고 성능 향상을 제공 할 수있는 경우를 제외하고는 어느 곳에서나 사용하는 것이 일반적으로 좋지 않습니다. 예를 들어 여기에서 느려진 것을 볼 수 있습니다.

\timing
CREATE TABLE foo AS
  SELECT * FROM generate_series(1,1e7);
Time: 5699.070 ms

CREATE TABLE foo AS
  WITH t AS ( SELECT * FROM generate_series(1,1e7) ) 
  SELECT * FROM t;
Time: 6484.516 ms

답변

WITH u AS (
    SELECT * FROM (VALUES (1, 'one'), (2, 'two'), (3, 'three')) AS account (id,name)
)
SELECT id, name, length(name) from u;