从切片中导出PostgreSQL中的文本文件(明年分发文本文件)

时间:2016-08-10 15:10:51

标签: postgresql

我有一个将结果导出到文本文件的查询。代码如下:

Copy (
      Select
           foo.gid As addr_ID, 
           bar.geom As streets,
           St_LineInterpolatePoint
               (ST_LineMerge(bar.geom),
                  St_LineLocatePoint
                     (St_LineMerge(bar.geom),foo.geom)
           ) As interpolated_point
      FROM foo
      Left JOIN bar ON ST_DWithin(foo.geom, bar.geom, 50)
      ORDER BY  
      foo.gid, St_Distance(foo.geom, bar.geom)
     )      
To '~path/my_file.txt' WITH DELIMITER ',';

表' foo'包含87行和' bar'包含16,060行。表' foo'还包含两列' start_time'和' end_time'描绘这样的不同年份的间隔:

Start_time              End_time
2003-06-07 00:00:00     2004-09-30 23:59:59
2004-02-03 00:00:00     2005-03-10 23:59:59
2003-07-09 00:00:00     2012-05-06 23:59:59

我想导出我的选择查询结果,以便它每年生成TEXT文件,如下所示:

预期输出:

results_2003.txt
results_2004.txt
results_2005.txt
and so on...

有人可以建议我怎么做吗?我在Windows 7 Enterprise(x64)上使用PostgreSQL版本9.5(x64)。

编辑(1):

每年需要导出文本文件,例如:In' start_time'和' end_time'列,如果下限是2003,上限是2012,那么每年的文件需要导出,如预期输出所示。

编辑(2):

到目前为止,我一直在尝试开发完整的工作代码(非常感谢@Phillip代码和建议的链接)但是我遇到了问题,因为我反复遇到语法错误。该错误表示"语法错误在" 1" (Where子句)。下面我发布了代码(再次CREDIT转到Phillip):

-- In the below code: Addr, streets, agfisotime (start time in data type timestamp) and agtisotime (end time in data type timestamp) are original columns

DO $$

DECLARE
start_year date;
end_year date;
current_year date;
file_name text;
 BEGIN
select date_trunc('year', min(agfisotime)), date_trunc('year', max(agtisotime))
  into start_year, end_year
  from Addr;

FOR current_year IN
    SELECT * FROM generate_series(start_year, end_year, interval '1 year')
LOOP

 Execute format('
    Copy(
        Select
        Addr.gid As addr_ID, 
        streets.geom As streets,
        St_LineInterpolatePoint(ST_LineMerge(streets.geom),
            St_LineLocatePoint(St_LineMerge(streets.geom),Addr.geom))
            As interpolated_point
        FROM Addr
        Left JOIN streets ON ST_DWithin(Addr.geom, streets.geom, 50)
        WHERE agfisotime < current_year + interval '1 year'
        AND agtisotime >= current_year
        ORDER BY  
        Addr.gid, St_Distance(Addr.geom, streets.geom)
    ) TO ''C:/temp/out.csv'';
    ',current_year);

END LOOP;
RETURN;
END
$$

1 个答案:

答案 0 :(得分:2)

这很复杂但有可能。基本问题是您需要为要写入的每个文件触发COPY命令一次,并且需要使用动态SQL执行此操作。这里有一个解释:Use function variable in dynamic COPY statement

要实际多次触发COPY命令,您需要使用匿名代码块或函数来检索年份列表,然后通过每年触发COPY命令导出。

我已经测试了以下内容,它显示了基本原则,尽管它没有导出正确的数据:

DO $$
DECLARE
    start_year date;
    end_year date;
    current_year date;
    file_name text;
BEGIN
    select date_trunc('year', min(start_time)), date_trunc('year', max(end_time))
      into start_year, end_year
      from foo;

    FOR current_year IN
        SELECT * FROM generate_series(start_year, end_year, interval '1 year')
    LOOP

    file_name := '/tmp/myFile_' || extract(year from current_year) || '.csv';

     --- do your export here using current_year to filter the results
    EXECUTE format('
        COPY (
           select start_time, end_time from foo
         WHERE start_time < %L::date + interval ''1 year''
           AND end_time >= %L::date
          )
        TO %L WITH DELIMITER '','';
        ',
    current_year, current_year, file_name);


    END LOOP;
END
$$;

每年您都需要过滤结果。所以你的查询看起来像这样(未经测试):

EXECUTE format('
    COPY (
Select
   foo.gid As addr_ID, 
   bar.geom As streets,
   St_LineInterpolatePoint
       (ST_LineMerge(bar.geom),
          St_LineLocatePoint
             (St_LineMerge(bar.geom),foo.geom)
   ) As interpolated_point
FROM foo
Left JOIN bar ON ST_DWithin(foo.geom, bar.geom, 50)
WHERE start_time < %L::date + interval ''1 year''
       AND end_time >= %L::date
ORDER BY  
foo.gid, St_Distance(foo.geom, bar.geom)

      )
    TO %L WITH DELIMITER '','';
    ',
current_year, current_year, file_name);