为时间表创建视图

时间:2015-01-28 22:58:42

标签: sql oracle oracle11g

我正在处理以下两个表格:

CREATE TABLE Consultant_Alloc ( 
    project_no      number(6),
    activity_no     number(4) NOT NULL,
    consultant_id   char(7) NOT NULL UNIQUE,
    allocated_hours number(3) NOT NULL,
    hours_worked    number(3),
        -- SUM(Consultant_Alloc.allocated_hours)
        CONSTRAINT pk_project_activity_consultant PRIMARY KEY (project_no, activity_no, consultant_id),
        CONSTRAINT fk_consultant_id FOREIGN KEY (consultant_id) REFERENCES Consultant (consultant_id)
            ON DELETE CASCADE,
        CONSTRAINT fk_project_no_activity_no_budget FOREIGN KEY (project_no, activity_no, budget) REFERENCES Activity (project_no, activity_no, budget_hours)
            ON DELETE CASCADE,

);


CREATE TABLE Activity (
    activity_no     number(4) NOT NULL,
    activity_name   varchar2(50),
    project_no      number(6) NOT NULL,
    allocated_hours number(3) CHECK (allocated_hours > 0),
    start_date      date, 
    end_date        date, 
    comp_date       date,

        CONSTRAINT pk_Activity_project_no_activity_no PRIMARY KEY (project_no, activity_no), -- Each activity must be unique
        CONSTRAINT fk_Activity_project FOREIGN KEY (project_no) REFERENCES Project (project_no)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
        CONSTRAINT ck_dates CHECK (start_date >= end_date)
);

我需要创建一个oracle SQL视图,详细说明上一个日历月中项目的工作小时数。我正在为我的业务学习这一点,并想了解我如何做到这一点,因为我不知道如何参考前一个日历月的所有项目。

由于

CREATE VIEW time_sheet 
AS SELECT CA.consultant_id CONSULTANT, A.project_no PROJECT, A.activity_no ACTIVITY, CA.hours_worked HOURS
FROM  Consultant_Alloc CA, Activity A
WHERE -- in previous calendar month
GROUP BY CA.consultant_id

这就是我要去的地方。

1 个答案:

答案 0 :(得分:0)

诀窍在于确定给定的日期范围是否与start_dateend_date的范围重叠,对吧? (或comp_date可以稍后?)我将假设范围start_dateend_date就足够了;如果你需要comp_date,你应该可以插入它。

确定交叉日期的公式如下所示:

(StartA <= EndB)  and  (EndA >= StartB)

在您的情况下,StartAstart_dateEndAend_date,而StartB则为上个月的第一天, EndB将是上个月的最后一天。但是,由于Oracle日期包含时间组件,我将说EndB当前月的第一天,并使用<而不是{{1 }}

所以要完成上个月发生的所有活动:

<=

如果我想将时间分配给特定项目,我可以执行以下操作:

SELECT activity_no, activity_name, project_no, allocated_hours
  FROM Activity
 WHERE start_date < TRUNC(sysdate, 'MONTH')
   AND end_date >= TRUNC(ADD_MONTHS(sysdate, -1), 'MONTH');

但是,这里的困难在于没有特定的活动日期;看起来它可以跨越不同的月份。这使得查找在特定月份中分配给项目的小时数很困难,如果不是不可能的话。我所能做的就是找到分配给给定项目的小时数,其中活动的日期范围与该月的天数范围相交。我认为,对于给定的活动,您应该有一个 log 表数小时,例如,

SELECT project_no, SUM(allocated_hours)
  FROM Activity
 WHERE start_date < TRUNC(sysdate, 'MONTH')
   AND end_date >= TRUNC(ADD_MONTHS(sysdate, -1), 'MONTH');
 GROUP BY project_no;

然后,我认为只有这样,您才能获得某个月内项目工作时间的报告:

CREATE TABLE activity_log
( activity_no NUMBER(4) NOT NULL
, consultant_id CHAR(7) NOT NULL
, log_hours NUMBER(3) CHECK (log_hours> 0)
, log_dt DATE DEFAULT SYSDATE NOT NULL
);

这样的表格还可以让您通过顾问进行细分:

SELECT a.project_no, SUM(al.log_hours)
  FROM activity a INNER JOIN activity_log al
    ON a.activity_no = al.activity_no
 WHERE TRUNC(log_dt, 'MONTH') = TRUNC(ADD_MONTHS(SYSDATE, -1), 'MONTH')
 GROUP BY a.project_no;

顺便说一下,除了在创建1个字符的列(例如SELECT a.project_no, al.consultant_id, SUM(al.log_hours) FROM activity a INNER JOIN activity_log al ON a.activity_no = al.activity_no WHERE TRUNC(log_dt, 'MONTH') = TRUNC(ADD_MONTHS(SYSDATE, -1), 'MONTH') GROUP BY a.project_no, al.consultant_id; 而不是CHAR时保存键击时,除了VARCHAR2之外,从来没有任何理由在Oracle中使用CHAR(1)VARCHAR2(1))。