2

我正在尝试根据正在搜索的星期几从表中选择 2 个费率列中的 1 个。我正在尝试对这个查询使用两个表:一个日历表(表名=日历,列名=caldates),它是一个严格的日期列表,其中每一行都是 2012 年 6 月 30 日到 2014 年 5 月 31 日之间的日期. 我还有另一个表(表名=rates),它有 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

有任何想法吗?

4

2 回答 2

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,所以没有匹配率的一天仍然会在结果中使用NULLas 率。

  • 当前接受的答案将星期日视为工作日,将星期五视为周末。我不认为这是预期的。
    CASE语句也可以简单得多,只需使用extract(isodow FROM source).

  • 您不必将结果转换为extract()to integer。我们比较的文字会double precision自动转换为匹配的类型。

于 2012-09-13T05:09:25.927 回答
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' ;
于 2012-09-13T02:30:30.047 回答