我有一个包含以下表格的数据库:
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);
现在我想要名单列表,按工资排序的所有员工的完整地址,并指出员工是全职还是休闲。此处名称是名称列中表示的FName和LName以及街道,郊区州邮政编码(例如123 Anzac Pde,Maroubra NSW 2038)的组合,标记为ADDRESS。现在我知道在Join Statements的帮助下完成它。但是如果我们应该在不使用JOIN语句的情况下这样做那么SQL查询可以解决这个问题吗?
我需要根据员工的工作类型从FULLTIME和CASUAL表中获取ADDRESS TABLE和Salary的地址
答案 0 :(得分:3)
您有表继承 - CASUALTIME
和FULLTIME
继承EMPLOYEE
。假设一个员工必须是随意的或全职的,并且不能同时休闲和全职,那么你可以做的是使用一个工会来组合派生表中的临时和全职员工(我称之为{{1在连接到其余表之前获取单个“salary”字段(您将需要连接):
x
在单一栏目中列出年薪和小时费率似乎有些奇怪,因为它们具有不同的单位 - 将小时费率转换为年薪更有意义,反之亦然,因此它们具有相同的意义单元。
另外,您shouldn't be using 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
存储财务数据 - 而不是使用DOUBLE
我还假设DECIMAL
是拼写错误 - 表格肯定是JOBTIME
?
答案 1 :(得分:2)
在Full Time
和Casual
中保留两张几乎完全相同的表似乎是错误的做法。
我会将它们合并到一个名为Salary
的表中,并将Emp_salary_yearly
和Emp_salary_hourly
重命名为Emp_salary
,因为您已经在JobType_ID
中都有CasualJob_ID
列表。此外,FullTimeJob_ID
和FromDate
列是多余且无用的。
请记住,任何员工的工资和工作类型都可能会发生变化,因此最好在工资表中保留ToDate
和NULL
列(使用{{1在ToDate
列中指示记录在当前日期仍然有效。
所以我的建议是这样的:
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)
<强>更新强> 回答你的意见: 首先,不要使用隐式连接。 ANSI-SQL现在支持显式连接超过20年,并且在隐式连接中确实没有更好的结果 显式连接比隐式连接更易读,更容易处理。
其次,如果2个工资表不能组合成一个,你可以在两者上使用LEFT JOIN,或者在派生表上使用INNER JOIN,这是UNION之间的结果StuartLC在his 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将为null。