0

I have one supertype table where I have to pick 1 subtype table from 2 subtypes a,b. A subtype cannot go with the other one so for me to query I have to check whether if the supertype id is contained on one of the subtypes. I have been doing experiment queries but cannot get it right.

This is what somehow I thought of:

SELECT * from supertypetable INNER JOIN 
IF  (a.id = given.id) then a ON a.id = supertypetable.id
ELSE  b ON b.id = supertetable.id

job Table
________________________________
|job_id| blach2x....
________________________________
|    1  |
|    2  |
|    3  |
________________________________

partime Table
________________________________
|job_id| blach2x....
________________________________
|    2  |
|    3  |
________________________________

fulltime Table
________________________________
|job_id| blach2x....
________________________________
|    1  |
|       |
________________________________

I want to join tables that satisfy my given id

4

3 回答 3

0

这看起来很像 rails/activerecord 中的多态连接。它在那里实现的方式是,“超类型”表有两个字段:subtype_id 和 subtype_type。subtype_type 表有一个字符串,可以很容易地变成正确的子类型表的名称;subtype_id 具有该表中行的 id。像这样构建表格可能会有所帮助。

您要问的下一个问题是您希望在结果中看到什么?如果您想查看超类型表和所有子类型表,您可能必须一次将它们连接起来,然后将它们合并在一起。换句话说,首先连接一个子类型表,然后连接下一个,等等。如果这不是你想要的,也许你可以进一步澄清你的问题。

于 2013-03-19T18:27:46.227 回答
0

如果 a.id 永远不能等于 b.id 您可以在两个表上进行连接,然后执行 UNION 并且只有 id 匹配的表才会返回结果:

SELECT * from supertypetable 
INNER JOIN 
a ON a.id = supertypetable.id
UNION
SELECT * from supertypetable 
INNER JOIN 
b ON b.id = supertypetable.id

如果 a.id 可以等于 b.id,那么这将不起作用。但这是一个想法

编辑评论:这种方法只有在 a 和 b 的结构相同的情况下才有效。

于 2013-03-19T18:29:53.167 回答
0

所以一个简单的建议可能就是:

   SELECT * FROM job
    left join parttime on parttime.job_id = job.job_id
    left join fulltime on fulltime.job_id = job.job_id
where job.job_id = @job_id

然后让您的应用程序找出两个连接表中的哪一个没有 NULL 数据并显示它。

如果您不介意不一致的数据集并且总是想要正确的返回集(尽管您仍然需要某种应用程序逻辑,因为正如您所说,parttime 和 fulltime 的结构是不同的,那么您怎么样在没有某种检查的情况下有条件地显示/使用他们的数据?如果你要进行检查,你不妨先做,找出给定的 job_id 子类型是什么,然后选择适当的查询在那里运行。)

对不起!题外话!

存储过程可以为您执行此逻辑(删除所有连接,仅作为示例):

CREATE PROCEDURE getSubTypeDATA (@job_id int)
BEGIN

IF (SELECT EXISTS(SELECT 1 FROM parttime WHERE job_id = @job_id)) = 1
BEGIN
SELECT * from parttime
END
ELSE
BEGIN
SELECT * from fulltime
END

END

或者,如果您想要一个一致的数据集(非常适合应用程序逻辑),为什么不将全职和兼职之间的公共列放入 UNION 语句,并为它们不共享的列创建硬编码的 NULL。例如,如果 fullTime 看起来像

EmployeeID、DepartmentID、Salary

和partTime看起来像

EmployeeID、DepartmentID、HourlyRate

你可以做

SELECT job.*, employeeid, departmentid, salary, null as hourlyrate FROM job inner join fulltime on fulltime.job_id = job.job_id
where job.job_id = ?
union
  SELECT job.*, employeeid, departmentid, null as salary, hourlyrate FROM job inner join parttime on parttime.job_id = job.job_id
where job.job_id = ?

如果有一百个不同的列,这可能会很笨拙。此外,如果这不明显,具有完全不同结构但使用相同外键的子类型是您打破第三范式的一个很好的线索。

于 2013-03-19T18:45:18.473 回答