1

我想创建一个包含员工、他们的工作、薪水和项目信息的数据库

我想保留项目成本的信息(项目的实际价值和员工投资的天数)

对于员工和项目,每个员工通过 PK 约束在项目中拥有一个角色,并允许将来添加新的角色类型(可能是“第三级”)。

    CREATE TABLE Employee(
      EmployeeID  INTEGER      NOT NULL PRIMARY KEY,
      Name        VARCHAR(30)  NOT NULL,
      Sex         CHAR(1)      NOT NULL,
      Address     VARCHAR(80)  NOT NULL,
      Security    VARCHAR(15)  NOT NULL,
      DeptID      INTEGER      NOT NULL,        
      JobID       INTEGER      NOT NULL
    );

    CREATE TABLE Departments  (
        DeptID   INTEGER     NOT NULL PRIMARY KEY,
        DeptName VARCHAR(30) NOT NULL
    );

    CREATE TABLE Jobs (
        JobID            INTEGER      NOT NULL PRIMARY KEY,
        JobName          VARCHAR(30)  NOT NULL,
        JobSalary        DOUBLE(15,3) NOT NULL default '0.000', 
        JobSalaryperDay  DOUBLE(15,3) NOT NULL default '0.000', 
        DeptID           INTEGER      NOT NULL
    );


    CREATE TABLE Project(
      ProjectID    INTEGER NOT NULL PRIMARY KEY,
      ProjectDesc   VARCHAR(200) NOT NULL,
      StartDate     DATE NOT NULL,
      EndDate       DATE NOT NULL, 
      DaysOfWork    INTEGER NOT NULL,
      NoEmployees   INTEGER NOT NULL,
      EstimatedCost DOUBLE(15,3) NOT NULL default '0.000', 
      RealCost      DOUBLE(15,3) NOT NULL default '0.000' 
    );


    CREATE TABLE `Project-Employee`(
      ProjectID    INTEGER NOT NULL,
      EmployeeID   INTEGER NOT NULL,
      Note         VARCHAR(200),
      DaysWork     INTEGER NOT NULL,
      CONSTRAINT fk_ProjectID  FOREIGN KEY (ProjectID)  REFERENCES Project(ProjectID),
      CONSTRAINT fk_EmployeeID FOREIGN KEY (EmployeeID) REFERENCES Employee(EmployeeID)
    );


INSERT INTO `Departments` VALUES (1, 'Outsourcing');
INSERT INTO `Departments` VALUES (2, 'Technician');
INSERT INTO `Departments` VALUES (3, 'Administrative');

INSERT INTO `Jobs` VALUES (1, 'welder'    ,500.550,16.7 ,2);
INSERT INTO `Jobs` VALUES (2, 'turner'    ,500.100,16.67,2);
INSERT INTO `Jobs` VALUES (3, 'assistant' ,650.100,21.67,2);
INSERT INTO `Jobs` VALUES (4, 'supervisor',800.909,26.70,3);
INSERT INTO `Jobs` VALUES (5, 'manager'   ,920.345,30.68,3);
INSERT INTO `Jobs` VALUES (6, 'counter'   ,520.324,17.35,1);



INSERT INTO `Employee` VALUES (10, 'Joe',  'M', 'Anywhere', '927318344', 1, 3);
INSERT INTO `Employee` VALUES (20, 'Moe',  'M', 'Anywhere', '827318322', 2, 3);
INSERT INTO `Employee` VALUES (30, 'Jack', 'M', 'Anywhere', '927418343', 3, 4);
INSERT INTO `Employee` VALUES (40, 'Marge','F', 'Evererre', '127347645', 1, 6);
INSERT INTO `Employee` VALUES (50, 'Greg' ,'M', 'Portland', '134547633', 3, 5);


INSERT INTO `Project` VALUES (1, 'The very first', '2008-7-04' , '2008-7-24' , 20, 5, 3000.50, 2500.00);
INSERT INTO `Project` VALUES (2, 'Second one pro', '2008-8-01' , '2008-8-30' , 30, 5, 6000.40, 6100.40);


INSERT INTO `Project-Employee` VALUES (1, 10, 'Worked all days'    , 20);
INSERT INTO `Project-Employee` VALUES (1, 20, 'Worked just in defs', 11);
INSERT INTO `Project-Employee` VALUES (1, 30, 'Worked just in defs', 17);
INSERT INTO `Project-Employee` VALUES (1, 40, 'Contability '       , 8);
INSERT INTO `Project-Employee` VALUES (1, 50, 'Managed the project', 8);

因此,要获得项目成本的总金额并将其用于未来的工作报价,我只需在汇总查询中汇总每个员工的每个工作的工作日。

知道参与特定项目的员工了解他们的工作产生的成本,将所有工作日求和的查询是什么,是否有可能通过这种设计知道这一点?

所以假设我知道在项目 1 中,有 5 名员工参与其中,并且我通过其他表“工作”知道我每天支付给他们每个人的薪水

我在这里用 sqlfiddle做一些查询

更新

 CREATE TABLE `Sexes` (
   Sex char(1) primary key
 );
 INSERT INTO Sexes values ('M');
 INSERT INTO Sexes values ('F');

CREATE TABLE `Employee`(
  EmployeeID  INTEGER      NOT NULL PRIMARY KEY,
  Name        VARCHAR(130)  NOT NULL,
  Sex         CHAR(1)      NOT NULL,
  Address     VARCHAR(380)  NOT NULL,
  Security    VARCHAR(15)  NOT NULL,
  FOREIGN KEY (Sex) references Sexes (Sex),
  CONSTRAINT `uc_EmployeeInfo` UNIQUE (`EmployeeID`,`Name`,`Security`)           
);

CREATE TABLE `Department`  (
  DeptID   INTEGER     NOT NULL PRIMARY KEY,
  DeptName VARCHAR(30) NOT NULL,
  CONSTRAINT `uc_DeptName` UNIQUE (`DeptID`,`DeptName`)
);

CREATE TABLE `Dept-Employee`(
  EmployeeID   INTEGER NOT NULL,          
  DeptID       INTEGER NOT NULL,     
  CONSTRAINT fk_DeptID     FOREIGN KEY (DeptID)     REFERENCES `Department`(DeptID),
  CONSTRAINT fk_EmployeeID FOREIGN KEY (EmployeeID) REFERENCES `Employee`(EmployeeID)
);

 CREATE TABLE `Dept-Manager`(
  EmployeeID   INTEGER NOT NULL,          
  DeptID       INTEGER NOT NULL,
  CONSTRAINT fk_DeptIDs     FOREIGN KEY (DeptID)     REFERENCES `Department`(DeptID),
  CONSTRAINT fk_EmployeeIDs FOREIGN KEY (EmployeeID) REFERENCES `Employee`(EmployeeID)
);

CREATE TABLE `Jobs` (
  JobID            INTEGER      NOT NULL PRIMARY KEY,
  JobName          VARCHAR(30)  NOT NULL,
  JobSalary        DECIMAL(7,3) NOT NULL default '0000.000', 
  JobSalaryperDay  DECIMAL(7,3) NOT NULL default '0000.000', 
  CONSTRAINT `uc_jobs` UNIQUE (`JobID`,`JobName`)
);

CREATE TABLE `Jobs-Employee`(
  EmployeeID   INTEGER NOT NULL,
  JobID        INTEGER NOT NULL,
  CONSTRAINT fk_JobIDs       FOREIGN KEY (JobID)      REFERENCES `Jobs`(JobID),
  CONSTRAINT fk_EmployeeIDss FOREIGN KEY (EmployeeID) REFERENCES `Employee`(EmployeeID)
);

CREATE TABLE `Project`(
  ProjectID     INTEGER NOT NULL PRIMARY KEY,
  ProjectName   VARCHAR(200) NOT NULL,
  StartDate     DATE    NOT NULL,
  DaysOfWork    INTEGER NOT NULL,
  NoEmployees   INTEGER NOT NULL,
  EstimatedCost DECIMAL(9,3) NOT NULL default '000000.000', 
  RealCost      DECIMAL(9,3) NOT NULL default '000000.000', 
  CONSTRAINT `uc_project` UNIQUE (`ProjectID`,`ProjectName`)           
);

CREATE TABLE `Project-Employee`(
  ProjectID    INTEGER NOT NULL,
  EmployeeID   INTEGER NOT NULL,
  Note         VARCHAR(200),
  DaysWork     INTEGER NOT NULL,
  CONSTRAINT fk_ProjectIDsss  FOREIGN KEY (ProjectID)  REFERENCES `Project`(ProjectID),
  CONSTRAINT fk_EmployeeIDsss FOREIGN KEY (EmployeeID) REFERENCES `Employee`(EmployeeID)
);


    INSERT INTO `Department` VALUES (1, 'Outsourcing');
    INSERT INTO `Department` VALUES (2, 'Technician');
    INSERT INTO `Department` VALUES (3, 'Administrative');

    INSERT INTO `Jobs` VALUES (1, 'welder'    ,500.550, 16.7 );
    INSERT INTO `Jobs` VALUES (2, 'turner'    ,500.100, 16.67);
    INSERT INTO `Jobs` VALUES (3, 'assistant' ,650.100, 21.67);
    INSERT INTO `Jobs` VALUES (4, 'supervisor',800.909, 26.70);
    INSERT INTO `Jobs` VALUES (5, 'manager'   ,920.345, 30.68);
    INSERT INTO `Jobs` VALUES (6, 'counter'   ,520.324, 17.35);

    INSERT INTO `Employee` VALUES (10, 'Joe',  'M', 'Joewhere', '927318344');
    INSERT INTO `Employee` VALUES (20, 'Moe',  'M', 'Moewhere', '827318322');
    INSERT INTO `Employee` VALUES (30, 'Jack', 'M', 'Jaswhere', '927418343');
    INSERT INTO `Employee` VALUES (40, 'Marge','F', 'Evererre', '127347645');
    INSERT INTO `Employee` VALUES (50, 'Greg' ,'M', 'Portland', '134547633');

    INSERT INTO `Dept-Employee`  VALUES (10,1);
    INSERT INTO `Dept-Employee`  VALUES (20,2);
    INSERT INTO `Dept-Employee`  VALUES (30,3);
    INSERT INTO `Dept-Employee`  VALUES (40,1);
    INSERT INTO `Dept-Employee`  VALUES (50,3);

    INSERT INTO `Jobs-Employee`  VALUES (10,3);
    INSERT INTO `Jobs-Employee`  VALUES (20,3);
    INSERT INTO `Jobs-Employee`  VALUES (30,4);
    INSERT INTO `Jobs-Employee`  VALUES (40,6);
    INSERT INTO `Jobs-Employee`  VALUES (50,5);

    INSERT INTO `Project` VALUES (1, 'The very first', '2008-7-04' , 20, 5, 3000.50, 2500.00);
    INSERT INTO `Project` VALUES (2, 'Second one pro', '2008-8-01' , 30, 5, 6000.40, 6100.40);

    INSERT INTO `Project-Employee` VALUES (1, 10, 'Worked all days'    , 20);
    INSERT INTO `Project-Employee` VALUES (1, 20, 'Worked just in defs', 11);
    INSERT INTO `Project-Employee` VALUES (1, 30, 'Worked just in defs', 17);
    INSERT INTO `Project-Employee` VALUES (1, 40, 'Contability '       , 8);
    INSERT INTO `Project-Employee` VALUES (1, 50, 'Managed the project', 8);

对于新结构,我这样做了

CREATE VIEW `Emp-Job` as
SELECT e.*,j.jobID  
FROM  Employee e,`Jobs-Employee` j
WHERE e.EmployeeID = j.EmployeeID;



CREATE VIEW `employee_pay` as
select e.*, j.jobname, j.jobsalary, j.jobsalaryperday
from `Emp-Job` e
inner join `Jobs` j
        on e.JobID = j.JobID;

create view project_pay as 
select pe.projectid, pe.employeeid, pe.dayswork,
       e.jobsalaryperday, (e.jobsalaryperday * dayswork) as total_salary
from `Project-Employee` pe
inner join `employee_pay` e
        on e.employeeid = pe.employeeid
4

1 回答 1

2

您问题末尾的数据似乎与您的 INSERT 语句中的数据不匹配。

你听说过“分而治之”吗?这是使用它的好时机。这就是我要做的。

create view employee_pay as
select e.*, j.jobname, j.jobsalary, j.jobsalaryperday
from employee e
inner join jobs j on e.jobid = j.jobid

create view project_pay as 
select pe.projectid, pe.employeeid, pe.dayswork,
       e.jobsalaryperday, (e.jobsalaryperday * dayswork) as total_salary
from project_employee pe
inner join employee_pay e
        on e.employeeid = pe.employeeid

会这样做,因为我希望这些观点通常是有用的。(尤其是调试。)创建了这些视图后,项目的总和非常简单。

select projectid, sum(total_salary) as total_salaries
from project_pay
group by projectid

projectid  total_salaries
--
1          1509.91

真的不想用 DOUBLE 来赚钱。请改用 DECIMAL


使用此查询来找出我的总和与您的不匹配的原因。

select p.*, e.name
from project_pay p
inner join employee e on e.employeeid = p.employeeid;

projectid  employeeid  dayswork  jobsalaryperday  total_salary  name
1          10          20        21.67            433.4         Joe
1          20          11        21.67            238.37        Moe
1          30          17        26.7             453.9         Jack
1          40           8        17.35            138.8         Marge
1          50           8        30.68            245.44        Greg

反模式

破碎的身份

每当你看到这样一张桌子

CREATE TABLE Departments  (
    DeptID   INTEGER     NOT NULL PRIMARY KEY,
    DeptName VARCHAR(30) NOT NULL
);

你应该假设它的结构是错误的,并深入挖掘。(在被证明无罪之前,它被假定为有罪。)您寻找的反模式

  • 整数作为人工主键,以及
  • 没有其他独特的约束。

像这样的表允许复制真实数据,消除了人工密钥的用处。

DeptID  DeptName
--
1       Wibble
2       Wibble
...
175     Wibble

像这样的表也将允许多个外键引用。这意味着一些外键可能引用 Wibble (DeptID = 1),一些可能引用 Wibble (DeptID = 175),等等。

要解决这个问题,请在 DeptName 上添加一个 UNIQUE 约束。

缺少外键引用

每当你看到这样一张桌子

CREATE TABLE Employee(
  EmployeeID  INTEGER      NOT NULL PRIMARY KEY,
  Name        VARCHAR(30)  NOT NULL,
  ...
  DeptID      INTEGER      NOT NULL,        
  JobID       INTEGER      NOT NULL
);

你应该假设它的结构是错误的,并深入挖掘。(同样,在被证明无罪之前,它被假定为有罪。)您寻找的反模式

  • 其他表中的 ID 号,以及
  • 没有引用这些表的外键约束。

要解决此问题,请为 DeptID 和 JobID 添加外键约束。在 MySQL 上,请确保您也在使用 INNODB 引擎。(从 MySQL 5.6 开始,MyISAM 仍然不会强制执行外键约束,但如果您编写它们,它不会给您错误或警告。它们被解析并忽略。)

如果你从另一个 dbms 来到 MySQL,你会惊讶地发现 MySQL 不支持内联外键引用语法。这意味着你不能写这个。

DeptID integer not null references Departments (DeptID)

相反,您必须在 CREATE TABLE 语句中编写单独的外键子句。(或者使用单独的 ALTER TABLE 语句来声明 FK 引用。)

DeptID integer not null,
foreign key (DeptID) references Departments (DeptID)

在此页面中搜索“inline ref”,但请阅读全文。

缺少 CHECK() 约束

MySQL 不强制执行 CHECK() 约束,因此对于请求 CHECK() 约束的列,您需要一个表和一个外键引用。当你看到这样的结构时

CREATE TABLE Employee(
  EmployeeID  INTEGER      NOT NULL PRIMARY KEY,
  Name        VARCHAR(30)  NOT NULL,
  Sex         CHAR(1)      NOT NULL,

“Sex”列请求 CHECK() 约束。

CREATE TABLE Employee(
  EmployeeID  INTEGER      NOT NULL PRIMARY KEY,
  Name        VARCHAR(30)  NOT NULL,
  Sex         CHAR(1)      NOT NULL CHECK( Sex IN ('M', 'F')),

但是 MySQL 不强制执行 CHECK() 约束,因此您需要另一个表和一个外键引用。

create table sexes (
  sex char(1) primary key
);
insert into sexes values ('M');
insert into sexes values ('F');

CREATE TABLE Employee(
  EmployeeID  INTEGER      NOT NULL PRIMARY KEY,
  Name        VARCHAR(30)  NOT NULL,
  Sex         CHAR(1)      NOT NULL,
  ...
  foreign key (Sex) references Sexes (Sex)

对于这些列中的大多数,我会考虑 CHECK() 约束。有些可以实现为具有外键引用的表。

  • 员工安全
  • Jobs.JobSalary
  • Jobs.JobSalaryperDay
  • Project.DaysOfWork
  • Project.NoEmployees
  • Project.EstimatedCost
  • 项目.RealCost
  • Project_Employee.DaysWork

使用浮点数据类型赚钱

不要那样做。浮点数是有用的近似值,但它们仍然是近似值。请改用 DECIMAL。

于 2012-11-07T01:43:08.700 回答