3

SQL から .csv にエクスポートしようとしていますが、特定の数の引数を受け入れるようにハードコーディングすると機能します。問題は、ユーザーが任意の数の引数を要求し、それらを where 句に渡せるようにしたいということです。コードはこれをもう少し明確にする必要があります。

create temporary table bdates as

 select tt.date, tt.time, tt.location
 from birthdays as bd
 inner join days as d
   on (d.id = bd.birth_id)
 inner join total_time as tt
   on (bd.date = tt.date and
       bd.time = tt.time and
       d.day_of = tt.location)
 where tt.date in(:date1, :date2) --defined by user at command line
 order by...

\copy bdates to '.csv'

だから私がやりたいと思うのは、明示的な :dates# 変数の代わりにその where 句にリストを渡すことです。たとえば、「2012-01-04 12:00, 2012-02-04 12:00, 2012-03-04 12:00」という引数を指定してスクリプトを実行することも、2 つまたは 1 つの引数のみを指定してスクリプトを実行することもできます。3 つの場合、文字列は '2012-01-04 12:00'、'2012-02-04 12:00'、'2012-03-04 12:00' に解析されます。

string_to_array()、unnest(regexp_matches(:dates, expression))、および regexp_split_to_table(:dates, expression) を試しましたが、結合の方法はわかりません。私が試したさまざまな解決策では、次のような多数のエラーが発生しました。

タイプ text[] をタイムゾーンなしでタイムスタンプにキャストすることはできません

タイプ レコードをタイム ゾーンなしでタイムスタンプにキャストすることはできません

regexp_split はグローバル オプションをサポートしていません

WHERE の引数はセットを返してはなりません

最後のものは特にがっかりします。私は途方に暮れており、何か意見をいただければ幸いです。これを行う簡単な方法がありますね。ありがとう!

4

2 に答える 2

2

これを試して:

create table x(d timestamp);

insert into x values
('jan 2, 2012'),
('february 4, 2012 12:00'),
('jan 4, 2012 12:00'),
('march 1, 2012'),
('may 3, 2012');

クエリ:

with input as
(
  select 
  '2012-1-2, 2012-01-04 12:00, 2012-02-04 12:00, 2012-03-04 12:00'::text
  as d_input
)
,converted_to_array as
(
  select ('{' || d_input || '}')::timestamp[] as d_array
  from input 
)
select d
from x cross join converted_to_array
where d = any(d_array)

出力:

D
January, 02 2012 00:00:00-0800
February, 04 2012 12:00:00-0800
January, 04 2012 12:00:00-0800

ライブ テスト: http://www.sqlfiddle.com/#!1/43d48/26


IN を使用して、配列を行にネスト解除することもできます。

with input as
(
  select 
  '2012-1-2, 2012-01-04 12:00, 2012-02-04 12:00, 2012-03-04 12:00'::text
  as d_input
)
,converted_to_array as
(
  select ('{' || d_input || '}')::timestamp[] as d_array
  from input 
)
select d
from x cross join converted_to_array
where d in (select unnest(d_array))

ライブ テスト: http://www.sqlfiddle.com/#!1/43d48/29


それらをすべて 1 行に入れることもできます。

select d
from x 
where d in (select unnest( ('{' || '2012-1-2, 2012-01-04 12:00, 2012-02-04 12:00, 2012-03-04 12:00'::text || '}')::timestamp[] ))

しかし、ここでstackoverflowで水平スクロールバーが発生するため、そうするのをためらっています:-)

ライブ テスト: http://www.sqlfiddle.com/#!1/43d48/31

于 2012-05-03T05:16:11.813 に答える
1

あなたはほとんど最も簡単で最速の方法を持っていました:

テスト テーブル:

CREATE TEMP TABLE t(d date);
INSERT INTO t VALUES
 ('2012-1-1')
,('2012-1-4')
,('2012-2-2')
,('2012-2-4')
,('2012-3-3')
,('2012-3-4');

タイムスタンプではなく日付でフィルタリングしているため、入力例を簡略化できます。

'2012-01-04 12:00, 2012-02-04 12:00, 2012-03-04 12:00'

に:

'2012-01-04, 2012-02-04, 2012-03-04'

クエリ (どちらの入力でも機能します):

SELECT t.*
FROM   t
JOIN  (SELECT unnest(string_to_array(
                    '2012-01-04, 2012-02-04, 2012-03-04', ', ')::date[]) AS d
    ) x USING (d)

次の方法でも実行できます。

       SELECT regexp_split_to_table(
                       '2012-01-04, 2012-02-04, 2012-03-04', ', ')::date AS d

しかしregexp_split_to_table()、遅いです。
一般に、JOIN行の選択は、比較的遅い よりも の方が高速IN()です。

于 2012-05-03T07:45:34.517 に答える