2012-05-03 16 views
3

SQLから.csvにエクスポートしようとしています。特定の数の引数を受け入れるようにハードコードすると機能します。物事は、私はユーザーが任意の数の引数を要求し、これらをwhere句に渡すことができるようにします。コードではこれをもう少し明確にする必要があります。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' 

は、だから私は、私がやりたいと思うものにリストを渡すことで、where句の代わりに、明示的な:日付#変数。たとえば、引数「2012-01-04 12:00、2012-02-04 12:00、2012-03-04 12:00」を使用してスクリプトを実行することも、引数を2つだけ使用することもできます。 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)を試しました。

キャストすることはできません型テキストは[]のタイムゾーンのないタイムスタンプする

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

regexp_splitがサポートしていません。私が試した様々なソリューションが含む多数のエラーを生成していますグローバルオプション

最後のものが特にがっかりするものであると私は途方に暮れだと、任意の入力をお願い申し上げセット

を返してはいけませんWHEREの引数。これを行う簡単な方法はありますか?ありませんか?ありがとう!

+0

正規表現は必要ありません。文字列のまわりに中かっこを入れて、タイムスタンプ[] '配列にキャストしてください。 –

+0

そして、配列にはINを使用できません。あなたはequalとANYを使用する必要があります。 'WHERE expr = ANY(arrayHere)' –

答えて

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


あなたも1行ですべてを置くことができる http://www.sqlfiddle.com/#!1/43d48/29


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

ライブテスト:

また、内の行にだけアンネスト配列を使用することができます

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

ライブテスト:あなたは日付、ないタイムスタンプにフィルタリングされているとして、あなたはあなたの例の入力を簡素化することができます

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

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

+0

こんにちは、これは有望ですね。私は朝にもっと近く見ていきます。 – user1229681

+0

素晴らしい。できます。複数のアプローチのおかげで、私はわずか2日間SQLで作業してきましたし、それぞれがどのように動作しているのか把握することは良いでしょう。ありがとう! – user1229681

1

あなたはほとんど最も簡単かつ最速の方法を持っていた

'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()

+0

ありがとう、これは役に立ちました! – user1229681