【问题标题】:Employee details with their Job Type员工详细信息及其工作类型
【发布时间】:2015-08-13 19:38:09
【问题描述】:

我有一个包含以下表格的数据库:

 create table EMPLOYEE
 (
   Emp_ID INT NOT NULL AUTO_INCREMENT,
   Emp_FName VARCHAR(30) NOT NULL,
   Emp_LName VARCHAR(30) NOT NULL,
   Address_ID_Resident INT REFERENCES ADDRESS(Address_ID),
   JobTime_ID CHAR(1) REFERENCES JOBTIME(JobTime_ID),
   PRIMARY KEY(Emp_ID)
 );

其他表地址如下:

 create table ADDRESS
 (
    Address_ID INT NOT NULL AUTO_INCREMENT,
    Address_St VARCHAR(50) NOT NULL,
    Address_City VARCHAR(30) NOT NULL,
    Address_State VARCHAR(3) NOT NULL,
    Address_PostCode CHAR(4) NOT NULL,
    Add_TypeID CHAR(1) REFERENCES ADDRESSTYPE(Add_TypeID),
    PRIMARY KEY(Address_ID)
 );

ADDRESSTYPE 表用于区分地址是住宅、办公室还是邮政

create table ADDRESSTYPE
(
  AddType_ID CHAR(1) NOT NULL,
  Add_Type VARCHAR(15) NOT NULL,
  PRIMARY KEY(AddType_ID)
);

JobTime Table 描述员工的工作是全职还是休闲。

Create table JOBTIME
(
  JobTime_ID CHAR(1) NOT NULL,
  JobTime_Desc VARCHAR(10) NOT NULL,
  PRIMARY KEY(JobTime_ID)
);

现在,由于他们每个人的薪水不同,所以对于全职和休闲,我们有两张单独的桌子。

 Create table FULLTIME
 (
   Emp_ID INT NOT NULL,
   Emp_salary_yearly DOUBLE(10,2) NOT NULL,
   JobType_ID INT REFERENCES JOBTYPE(JobType_ID),
   FullTimeJob_ID CHAR(1) NOT NULL DEFAULT 'F',
   PRIMARY KEY(Emp_ID)
  );

  ALTER TABLE FULLTIME ADD FOREIGN KEY(Emp_ID) REFERENCES EMPLOYEE(Emp_ID);

  ALTER TABLE FULLTIME ADD FOREIGN KEY(FullTimeJob_ID) REFERENCES JOBFULLTIME(FullTimeJob_ID);

 Create table CASUALTIME
 (
   Emp_ID INT NOT NULL,
   Emp_salary_hourly DOUBLE(10,2) NOT NULL,
   JobType_ID INT REFERENCES JOBTYPE(JobType_ID),
   CasualJob_ID CHAR(1) NOT NULL DEFAULT 'C',
   PRIMARY KEY(EMP_ID)
 );

 ALTER TABLE CASUALTIME ADD FOREIGN KEY(Emp_ID) REFERENCES EMPLOYEE(Emp_ID);

 ALTER TABLE CASUALTIME ADD FOREIGN KEY(CasualJob_ID) REFERENCES JOBCASUALTIME(CasualJob_ID);

现在我想要按薪水排序的所有员工的姓名列表、完整地址,并指明该员工是全职工作还是临时工作。这里的 name 是 Name 列中表示的 FName 和 LName 的组合,以及标记为 ADDRESS 的列中 Street, Suburb State Postcode(例如 123 Anzac Pde, Maroubra NSW 2038)的组合。现在我知道在加入语句的帮助下做到这一点。但是,如果我们应该在不使用 JOIN 语句的情况下执行此操作,那么针对此问题的 SQL Query 可以是什么?

我需要根据员工的工作类型从 ADDRESS TABLE 中获取地址,并从 FULLTIME 和 CASUAL 表中获取薪水

【问题讨论】:

  • 到目前为止您尝试过什么查询?
  • @Sachu 我在如何将 Emp_salary_yearly 和 Emp_salary_hourly 合并到一个列中遇到问题?
  • 你不认为地址表应该有代表员工ID的列!我刚刚检查了前两个表,但我不知道你还能如何获取员工地址!
  • @ubaidgadha 员工表具有地址表的 FK。有些员工可能住在一起,所以这是正确的关系。
  • 双(10,2)。 ??我能有工作吗。我不介意我不知道我得到了多少百万的确切报酬,所以我可能可以不用 DECIMAL 数据类型来生活

标签: mysql sql


【解决方案1】:

您有表继承 - CASUALTIMEFULLTIME 继承 EMPLOYEE。假设员工必须是临时员工或全职员工,并且不能同时是临时员工和全职员工,那么您可以使用工会将临时员工和全职员工合并到派生表中(我称之为 x ),并在加入其余表之前获取单个“薪水”字段(您将需要加入):

 SELECT e.Emp_FName, e.Emp_LName, a.Address_St, a.Address_City, 
        a.Address_State, a.Address_PostCode, x.Salary
 FROM 
 (
    SELECT ct.emp_id, ct.Emp_salary_hourly AS Salary
    FROM CASUALTIME ct

    UNION

    SELECT ft.emp_id, ft.Emp_salary_yearly AS Salary
    FROM FULLTIME ft
 ) x
 INNER JOIN  EMPLOYEE e on x.Emp_ID = e.Emp_ID
 INNER JOIN ADDRESS a on e.Address_ID_Resident = a.Address_ID
 -- Can join to JobType and AddressType same way

在单个列中列出年薪和小时工资似乎有点奇怪,因为它们具有不同的单位 - 将小时工资转换为年工资会更有意义,反之亦然,因此它们具有相同的单位。

另外,你 shouldn't be using DOUBLE 来存储财务数据 - 而不是使用 DECIMAL

我还假设 JOBTIME 是一个错字 - 表格肯定是 JobType

【讨论】:

  • 我不想直接加入我想使用 WHERE 子句加入多个表
  • 使用WHERE to join tables is frowned upon - 使用 ANSI 连接是前进的方向 - 我不明白你为什么要养成坏习惯?无论如何,语法是FROM (SELECT...) x, Employee e, ... WHERE e.Emp_ID = x.Emp_ID AND ...
  • 你能把它添加到你的答案帖子中吗?我还需要打印按薪水排序的结果
  • 不,MySql 支持 ANSI 连接,您应该使用这些连接,而不是 WHERE 子句
  • 请注意,SO 不是代码编写服务——您正在添加新的需求。有一个look here
【解决方案2】:

Full TimeCasual 保留两个几乎相同的表在我看来是错误的做法。
我会将它们合并到一个名为Salary 的表中,并将Emp_salary_yearlyEmp_salary_hourly 重命名为Emp_salary,因为您已经在两个表中都有JobType_ID 的列。此外,CasualJob_IDFullTimeJob_ID 列是多余且无用的。

请记住,任何员工的薪水和工作类型都可能发生变化,因此最好在薪水表中也保留 FromDateToDate 列(在 @987654336 中使用 NULL @ 列表示记录在当前日期仍然有效)。

所以我的建议是这样的:

Create table Salary
(
    Emp_ID INT NOT NULL REFERENCES EMPLOYEE(Emp_ID),
    Emp_salary DOUBLE(10,2) NOT NULL,
    JobType_ID INT REFERENCES JOBTYPE(JobType_ID),
    FromDate date NOT NULL,
    ToDate date NULL,
    PRIMARY KEY(Emp_ID, FromDate)
);

注意:此表的主键既是员工 ID,也是起始日期。

这将使一个简单的 sql 语句看起来像这样:

SELECT CONCAT(Emp_FName, ' ', Emp_LName) As FullName, 
       CONCAT(Address_St, ' ', Address_City, ' ', Address_PostCode) As Address,
       Emp_salary_yearly,

       JobType_Desc,
       FromDate,
       ToDate
FROM EMPLOYEE e 
INNER JOIN ADDRESS a ON e.Address_ID_Resident = a.Address_ID
INNER JOIN Salary s ON(e.Emp_Id = Salary.Emp_Id)
INNER JOIN JOBTYPE j ON(s.JobType_ID = j.JobType_ID)

更新 回答你的cmets: 首先,不要使用隐式连接。 ANSI-SQL 支持显式连接已有 20 多年了,而隐式连接确实没有比这更好的了。
显式连接比隐式连接更具可读性和更易于处理。

其次,在 2 个工资表不能合并为一个的情况下,您可以在两者上使用 LEFT JOIN,或者在派生表上使用 INNER JOIN,这是它们之间 UNION 的结果由StuartLChis answer. 中建议

这是使用左连接的样子:

SELECT CONCAT(Emp_FName, ' ', Emp_LName) As FullName, 
       CONCAT(Address_St, ' ', Address_City, ' ', Address_PostCode) As Address,
       CASE WHEN Emp_salary_hourly IS NOT NULL THEN  
               CONCAT('$', LPAD(Emp_salary_hourly, 7, ' ') 
            WHEN Emp_salary_yearly IS NOT NULL THEN  
               CONCAT('$', LPAD(Emp_salary_yearly , 7, ' ')
       END As Emp_Salary, 
       JobType_Desc,
       FromDate,
       ToDate
FROM EMPLOYEE e 
INNER JOIN ADDRESS a ON e.Address_ID_Resident = a.Address_ID
INNER JOIN JOBTIME j ON(e.JobTime_ID = j.JobTime_ID )
LEFT JOIN FULLTIME f ON(e.Emp_Id = f.Emp_Id)
LEFT JOIN CASUALTIME c ON(e.Emp_Id = c.Emp_Id)

注意事项 #1: 这假设员工只能有一个工作时间。
注意事项 #2: 如果 FULLTIME 和 CASUALTIME 都没有记录对于 emp_id,则 Emp_Salary 将为空。

【讨论】:

  • 我不想直接加入我想使用 WHERE 子句加入多个表。我也不能像这样合并这两个表。原因是我只在这里提供了一部分表。我在我的项目中以不同的方式整体使用这两个表
  • 另外你可能没有注意到它们都依赖于两个不同的表名 JOBFULLTIME 和 JOBCASUALTIME
  • 如何写 Emp_salary 如果所有货币值都应该用美元符号 ($) 打印,小数点后两位数,小数点前 7 位空格
  • 参见this answer 了解如何在 MySql 中格式化数据
  • 它不寻找 7 个空格
猜你喜欢
  • 2020-10-08
  • 2016-01-28
  • 1970-01-01
  • 2020-11-22
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
相关资源
最近更新 更多