2012-05-03 47 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'運行腳本,或者只運行兩個參數或一個參數。在三個字符串將被解析爲'2012-01-04 12:00','2012-02-04 12:00','2012-03-04 12:00'。我試過string_to_array(),unnest(regexp_matches(:日期,表達式))和regexp_split_to_table(:日期,表達式),但我不知道如何做連接。我已經嘗試了各種解決方案已經產生了許多錯誤,包括:

不能投類型的文本[]沒有時區時間戳

不能投射式記錄的時間戳沒有時區

regexp_split不支持全局選項

的WHERE不能返回一套

最後一個參數是特別令人沮喪,我很茫然,並希望任何輸入。有一個更簡單的方法來做到這一點,不是嗎?謝謝!

+0

你不需要正則表達式,只需在字符串周圍放一個大括號,然後將它轉換爲'timestamp []'數組 –

+0

並且不能使用IN作爲數組。你必須使用平等和任何。 '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


您也可以使用,只是UNNEST數組行:

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


你可以把他們都在一個太行:

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

但我猶豫要這樣做,因爲它會導致水平滾動條在這裏的計算器:-)

現場測試:http://www.sqlfiddle.com/#!1/43d48/31

+0

嘿,謝謝你,這看起來很有希望。我會在早上仔細看看。 – user1229681

+0

真棒。有用。感謝您使用多種方法,我只用了兩天的時間就可以瞭解sql,這對了解每種方法的工作原理都很有幫助。謝謝! – user1229681

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 regexp_split_to_table(
         '2012-01-04, 2012-02-04, 2012-03-04', ', ')::date AS d 

regexp_split_to_table()較慢:

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) 

也有工作要做。
通常,JOIN選擇行的速度要快於相對較慢的IN()

+0

謝謝,這很有幫助! – user1229681