3

我的表包含以下结构:

START_DATE | END_DATE   | COST
2012-11-01 | 2012-11-05 | 500.5

我想执行一个返回以下结果的 SELECT 语句:

DATE       | COST
2012-11-01 | 100.1
2012-11-02 | 100.1
2012-11-03 | 100.1
2012-11-04 | 100.1
2012-11-05 | 100.1

我可以弄清楚如何将总成本除以开始日期和结束日期之间的天数,但不知道如何为 DATE 列创建这些“虚拟行”。

也许根本不可能。很感谢任何形式的帮助!

4

3 回答 3

3

最好的办法是创建一个Calendar表。

出于您的目的,您只需要一列...

CREATE TABLE Calendar AS (calendar_date DATE)

然后你用你感兴趣的所有日期填满这张表。即使是一百年,这张表仍然很小。

请记住将该列添加为主键。

然后你就加入到桌子上......

SELECT
  *
FROM
  yourTable
INNER JOIN
  calendar
    ON  calendar.calendar_date >= yourTable.start_date
    AND calendar.calendar_date <= yourTable.end_date

稍后您可能会发现您想知道假期日期、财政年度边界等。这些都可以作为附加字段和索引添加到该日历表中。

它很像缓存,而不是在查询中重新计算混乱的基于日期的规则。

或者,您可以将其视为一个维度表,其中数据是 ID,其他列是事实。

于 2012-11-14T10:56:03.577 回答
2

我同意Dems有一个日历表,这是最好的选择。因为 Mysql 没有像许多其他 RDBMS 那样的 ROW_NUMBER 函数。

另一种选择是创建一个带有序列号的表。您可以使用大量值(例如 1 到 100k)填充此表,您认为这将是任何 start_date 和 end_date 之间的最大天数

就像是

create table seq

(rn int);

insert into seq
select 0 as rn union all
select 1 as rn union all
select 2 as rn union all
select 3 as rn union all
select 4 as rn union all
select 5 as rn 

然后运行以下查询:

select DATE_ADD(START_DATE, INTERVAL rn day) ,
       COST/(select datediff(END_DATE,START_DATE)+1 from table1)
from Table1
cross join seq
where rn<=(select datediff(END_DATE,START_DATE) from table1)


SQL小提琴演示

于 2012-11-14T11:02:34.787 回答
0

我同意你 Sebas 的观点,这个在 oracle 中工作。用你的表名代替 table1

如果您无权访问,all_objects

select ( I +START_DATE-1) date1,cost/((END_DATE-START_DATE)+1) cost from table1 ,(     select I  from DUAL
              model
              dimension by (1 i)
              measures (0 X)
              (X[for I from 2 to 10000 increment 1] = 0)) 
              where END_DATE>=I +START_DATE-1;

如果您可以访问元表,all_objects那么试试这个

SELECT DATE1.DATE_ALL, table1.cost/((table1.END_DATE-table1.START_DATE)+1) NEW_COST 
FROM table1 INNER JOIN 
    (
     SELECT START_DATE + rownum-1 DATE_ALL 
     FROM ALL_OBJECTS
             CROSS JOIN table1
     WHERE 
         START_DATE + rownum - 1 <= (SELECT MAX(END_DATE) FROM table1)
    ) DATE1 ON table1.END_DATE >= DATE1.DATE_ALL

如果您有任何问题,请告诉我。

于 2012-11-14T14:56:08.527 回答