TEACHER_TB
NUMBER VARCHAR VARCHAR VARCHAR DATE NUMBER NUMBER
TEACHER_ID FIRST NAME LAST NAME GENDER DOB SALARY_ID SUBJECT_ID
1 Bob Sandreas M 12-May-60 1 2
2 Michella Farah F 24-Dec-80 3 4
3 Montessa Santos F 10-Feb-73 3 8
4 John Reyes M 28-Feb-88 2 6
5 Lara Saliba F 15-Aug-73 2 10
6 Rizvi Ibrahim M 9-May-65 1 3
7 Raphael Legaspi M 5-Sep-91 2 5
8 Alaa Badawy M 27-Jan-85 2 4
9 Jahangir Alam M 28-Jul-57 1 9
10 Peter Parker M 5-Jun-92 1 6
primary key foreign key salary_tb(salary_id) foreign key subject_tb(subject_id)
SALARY_TB
NUMBER VARCHAR VARCHAR VARCHAR VARCHAR VARCHAR VARCHAR
SALARY_ID BASIC HOUSING TRANSPORTATION TELEPHONE PPF TDS
1 Y Y Y Y Y Y
2 Y Y N N Y Y
3 Y Y N N N Y
primary key
SALARY_COMPONENTS_TB
NUMBER VARCHAR VARCHAR VARCHAR
COMPONENT_ID SALARY_COMPONENT COMPONENT_TYPE AMOUNT
1 BASIC EARNING 40000
2 HOUSING EARNING 20000
3 TRANSPORTATION EARNING 10000
4 TELEPHONE EARNING 5000
5 PPF DEDUCTION 5%
6 TDS DEDUCTION 10%
有3个表(TEACHER_TB,SALARY_TB,SALARY_COMPONENTS_TB),其中前2个表已链接,但没有与SALARY_COMPONENTS_TB的连接(没有表与SALARY_COMPONENTS_TB连接),所以我需要找出教师工资SALARY_COMPONENT(总和)。 / p>
我们可以在两个表之间没有任何关系的情况下链接两列吗?
答案 0 :(得分:0)
"我们可以在两个表之间没有任何关系的情况下链接两列吗?"
当然。我们可以加入任何东西。只是有些连接是有意义的而其他人没有。外键的目的是强制实现关系。外键的存在也可以作为有意义的连接的指示。
"没有与SALARY_COMPONENTS_TB"
的关联
您需要根据SALARY_COMPONENTS_TB
中的列和SALARY_TB
中的行将SALARY_TB
加入SALARY_COMPONENTS_TB
。这是一个支点。执行此操作有多种不同的方法是MySQL,但硬编码值是最简单的(如果不是最易维护的,但请参见下面的注释)。
计算扣减是混乱的,因为相关的amount
值存储为非数字字符串。 '10%'
可能对人类友好,但最好存储一个适合算术的值,即0.10
。
无论如何这里是一个查询:
select t.teacher_id
, t.salary_id
, (sal.basic+sal.housing+sal.transportation+sal.telephone) as salary_gross
, (sal.ppf + sal.tds) as salary_deduct
, (sal.basic+sal.housing+sal.transportation+sal.telephone)
- ( (sal.basic+sal.housing+sal.transportation+sal.telephone)
* (sal.ppf + sal.tds) ) as salary_net
from teacher_tb as t
join (
select s.SALARY_ID
, case when (basic='Y') then scb.amount else 0 end as basic
, case when (housing='Y') then sch.amount else 0 end as housing
, case when (transportation='Y') then sct.amount else 0 end as transportation
, case when (telephone='Y') then scp.amount else 0 end as telephone
, case when (ppf='Y') then round(substring(ppf.amount,1, length(ppf.amount)-1)/100,3) else 0 end as ppf
, case when (tds='Y') then round(substring(tds.amount,1, length(tds.amount)-1)/100,3) else 0 end as tds
from salary_tb as s
cross join salary_components_tb scb
cross join salary_components_tb sch
cross join salary_components_tb sct
cross join salary_components_tb scp
cross join salary_components_tb ppf
cross join salary_components_tb tds
where scb.salary_component = 'BASIC'
and sch.salary_component = 'HOUSING'
and sct.salary_component = 'TRANSPORTATION'
and scp.salary_component = 'TELEPHONE'
and ppf.salary_component = 'PPF'
and tds.salary_component = 'TDS'
) as sal
on t.salary_id = sal.salary_id
;
人们常常不喜欢被告知他们正在使用糟糕的数据模型,他们总是有充分的理由不改变它。但StackOverflow的目的是帮助人们成为更好的程序员。因此,拥有一个好的数据模型很重要,不仅因为关系完整性至关重要,而且因为它使得编写漂亮干净的SQL更容易。
在你的情况下,SALARY_COMPONENTS_TB
比无意义更糟糕。首先,它会强制您在每次需要在查询中使用数据透视表时对其进行编码。这使得查询难以理解并且维护起来更耗时。但是也没有数据完整性。您可以在该表中放置任何内容或删除任何内容;我不保证您({say)salary_component = 'HOUSING'
有一行,不保证amount
将包含您可以在算术中使用的可预测值。
那么什么是更好的数据模型?使用存储实际值的数字列替换SALARY_TB
上的标志列。使用起来更容易,因为它们可能是(应该是)数字列,您可以在算术中使用它而不需要复杂的字符串操作和数据类型转换。好多了。