为时间表创建视图

Create a view for a timesheet

我正在处理以下 2 个表:

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

这就是我要去的地方。

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

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

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

在您的情况下,StartA 将是 start_date,而 EndA 将是 end_date,而 StartB 将是上个月的第一天, EndB 将是上个月的最后一天。但是,由于 Oracle 日期包含时间部分,我要说 EndB 当前 月份的第一天,并使用 < 而不是<=.

所以要获取上个月发生的所有活动:

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');

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

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;

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

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;

这样的 table 也能让您得到顾问的细分:

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;

顺便说一下,在 Oracle 中没有任何理由在 VARCHAR2 上使用 CHAR,除非在创建 1 个字符的列时节省击键(例如,CHAR(1)而不是 VARCHAR2(1)).