Sql选择多个子表之一
我对SQL并不陌生,但我不是一名db经理/设计师,因此遇到了一些难题。我有一个父表(父表有子表的共享属性),它有8个子表。当我查询数据库时,我需要来自父表的数据,一次只需要一个子表,但是我很难确定如何与哪个子表通信。父表和子表共享一个id。父表中的字段有可能成为从中提取子表的决策者。例如:Sql选择多个子表之一,sql,Sql,我对SQL并不陌生,但我不是一名db经理/设计师,因此遇到了一些难题。我有一个父表(父表有子表的共享属性),它有8个子表。当我查询数据库时,我需要来自父表的数据,一次只需要一个子表,但是我很难确定如何与哪个子表通信。父表和子表共享一个id。父表中的字段有可能成为从中提取子表的决策者。例如: parent id机 1 N1 2 S8 3 P6 仅包含与具有“N”类型计算机(N1、N2、N3,…)的父记录关联的记录。 child1 id…其他一些列 1 仅包含与具有“S”类型计算机(S1、S2、S3
parent
id机
1 N1
2 S8
3 P6
仅包含与具有“N”类型计算机(N1、N2、N3,…)的父记录关联的记录。
child1
id…其他一些列
1
仅包含与具有“S”类型计算机(S1、S2、S3,…)的父记录关联的记录。
child2
id…其他一些列
2
仅包含与具有“p”类型计算机(P1、P2、P3,…)的父记录关联的记录。
child3
id…其他一些列
3
我在这里看到了几个似乎效率不高的逻辑可能性:1) 依次在每个子表中搜索父表中记录的id 2) 使用join语句创建视图,该语句包含附加到关联父记录的所有子表记录。这难道不会变成一个巨大的空值格子糖球吗 3) 为每个子表创建一个视图,将父记录和子记录连接到一个表中。用另一种语言创建某种机制,将机器翻译成它的类型(例如:如果我想要
N1
的记录,所述代码将为包含child1的视图(N
type机器表)设置查询“表”。(可能是三种机器表中最好的选择?)
我忍不住觉得我在这里遗漏了一些东西,一些SQL魔法会让这个问题看起来很简单,但是对inter-webs的搜索没有产生任何结果。您能给我的任何东西都将不胜感激。非常感谢。您可以做这些
连接的方法是对所有表进行左连接选择产品类型,然后在选择中对所有产品使用合并:
SELECT p.id,
P.machine,
P.someField,
COALESCE(C1.field, C2.field, C3.field) field
FROM parent P
LEFT JOIN child1 C1 ON C1.id = P.id
AND LEFT(P.machine, 1) = 'N'
LEFT JOIN child2 C2 ON C2.id = P.id
AND LEFT(P.machine, 1) = 'S'
LEFT JOIN child3 C3 ON C3.id = P.id
AND LEFT(P.machine, 1) = 'P';
然而,这样做是非常昂贵的
一种更好的方法是使用一个具有其所在机器类型的子表(例如,MachineType Char(1)
列,该列中只有N
、S
、p
等),而不是使用8个不同的表
另一种选择是使用UNION ALL
单独引入项目:
SELECT p.id,
P.machine,
P.someField,
C1.field field
FROM parent P
JOIN child1 C1 ON C1.id = P.id
WHERE LEFT(P.machine, 1) = 'N'
UNION ALL
SELECT p.id,
P.machine,
P.someField,
C2.field field
FROM parent P
JOIN child2 C2 ON C2.id = P.id
WHERE LEFT(P.machine, 1) = 'S'
UNION ALL
SELECT p.id,
P.machine,
P.someField,
C3.field field
FROM parent P
JOIN child3 C3 ON C3.id = P.id
WHERE LEFT(P.machine, 1) = 'P'
您可以将每个子表解压为列名/值,并将它们合并到一个视图中(如果这是一个更有利的输出)。根据您的SQL FIDLE:
--Unpivoted Children
CREATE VIEW unpvt_child AS
--N Machine Children
SELECT
unpvt.id,
unpvt.col_name,
unpvt.col_value
FROM
(SELECT id, c1_field1
FROM child1) p
UNPIVOT
(col_value FOR col_name IN
(c1_field1)
)AS unpvt
UNION ALL
--S Machine Children
SELECT
unpvt.id,
unpvt.col_name,
unpvt.col_value
FROM
(SELECT id, c2_field1
FROM child2) p
UNPIVOT
(col_value FOR col_name IN
(c2_field1)
)AS unpvt;
这将为您提供如下输出:
id, col_name, col_value
1, c1_field1, N machine stuff
2, c2_field1, S machine stuff
id, machine, someField, child_attribute, child_value
1, N1, blah, c1_field1, N machine stuff
2, S8, moreblah, c2_field1, S machine stuff
如果我理解模式,主键是id,它与子表是一对一的,因此新的连接很简单:
SELECT
*
FROM
parent p
LEFT JOIN
unpvt_child c ON c.id = p.id;
SQL Fiddle:
您的最终输出可以如下所示:
id, col_name, col_value
1, c1_field1, N machine stuff
2, c2_field1, S machine stuff
id, machine, someField, child_attribute, child_value
1, N1, blah, c1_field1, N machine stuff
2, S8, moreblah, c2_field1, S machine stuff
在这里,我假设所有CHILD
表都包含相同类型的列。您是否可以在一个新表中插入所有CHILD
表数据,并添加一个额外的MACHINE\u TYPE
指示符列,如P6、S8。MACHINE\u TYPE
也将帮助您与PARENT
表连接。不幸的是,没有ld表都包含不同的列,因此它将使一个巨大的表充满空值。如果可以的话,我想避免这种情况。我现在可以想到的是两步解决方案。创建一个包含两列的新表,即MACHINE\u TYPE
和CONCATENATED
所有其他带有分隔符(如逗号)的列。此表将帮助您连接。现在对于select,您可以使用内置函数轻松地转换行中的
分隔文本列。子表包含不同类型的列。@Minaverma我确信它们包含不同类型的列,但我不知道这有什么关系。组合子表的问题是每个表包含不同的列集,我不想以mor结束e空值大于填充值。我想我开始得出结论,我需要8个不同的视图,每个视图都包含一组父列和子列……其他方面,我最终会得到很多空值。@JoeMilo这是一个选项,您可以为每种类型创建一个视图,并通过一个UNION ALL
将它们组合到一个查询中(本质上,这正是我的第二个查询建议所做的)@Siyual我明白你的意思了,但是,我忽略了一点,那就是表的行数都不一样。我刚刚测试了你的代码,在child3中添加了第二列,它不能处理不同的行数,所以我只能查询几个视图,但我真的很喜欢你的代码片段,这是一个非常酷的例子使用并集和联接。