我正在尝试根据正在搜索的星期几从表中选择2个速率列中的1个。我试图为这个查询使用两个表:一个日历表(表名=日历,列名= caldates),这是一个严格的日期列表,其中每一行是2012-06-30和2014-05-31之间的日期。我还有另一个表(表名=费率)有4列:start_date,end_date,weekday_rate和weekend_rate。
Start_date end_date weekday_rate weekend_rate
"2012-05-01" "2012-06-30" 69 150
"2012-07-01" "2012-08-31" 74 200
"2012-09-01" "2012-11-14" 75 210
"2012-11-15" "2013-01-31" 90 150
执行查询时,系统需要查找正确的费率。现在我的查询看起来像这样:
SELECT
CASE cast(extract(dow from caldates) as int)
WHEN '0' then (select weekday_rate from rates)
WHEN '1' then (select weekday_rate from rates)
WHEN '2' then (select weekday_rate from rates)
WHEN '3' then (select weekday_rate from rates)
WHEN '4' then (select weekday_rate from rates)
WHEN '5' then (select weekend_rate from rates)
When '6' then (select weekend_rate from rates)
End AS the_date_rate
FROM calendar WHERE caldates >= '2012-08-30' and caldates <= '2012-09-04' ;
当我运行查询时,收到错误“错误:用作表达式的子查询返回的多行。”
我希望输出显示日期范围以及与日期相关的费率。上面的例子看起来像
caldates the_date_rate
2012-08-30 74
2012-08-31 200
2012-09-01 210
2012-09-02 75
2012-09-03 75
2012-09-04 75
有什么想法吗?
答案 0 :(得分:1)
这可以大大简化。
SELECT d.day
,CASE WHEN extract(isodow from d.day) < 6
THEN weekday_rate
ELSE weekend_rate
END AS rate
FROM (SELECT generate_series('2012-06-30'::date
,'2014-05-31'::date, '1d'::interval)::date AS day
) d
LEFT JOIN rates r ON d.day BETWEEN r.start_date AND r.end_date
ORDER BY d.day
对于PostgreSQL中无间隙的一系列日期,您不需要calendar
表。请改为使用generate_series()
代替。
您需要加入rates
表。目前接受的答案根本不起作用。
我使用的是LEFT JOIN
,所以没有匹配率的日子仍然会以NULL
为结果。
目前接受的答案将星期日视为工作日,星期五视为周末。我不认为这是预期的。
使用extract(isodow FROM source)
只有两种情况,CASE
语句也可以简单得多。
您无需将extract()
的结果投射到integer
。我们比较的文字将自动转换为匹配类型double precision
。
答案 1 :(得分:0)
这就足够了(同时看看你是否真的需要在when子句之后的星期日值附近引用):
SELECT
CASE
WHEN cast(extract(dow from caldates) as int) < 6 then weekday_rate
ELSE weekend_rate
End AS the_date_rate
FROM
calendar
WHERE
caldates >= '2012-08-30' and caldates <= '2012-09-04' ;