获取信息'A'您想从数据库中获取信息'E'。它们之间没有直接连接,因此您必须选择使用多个表。例如,您可以使用INNER JOIN
来实现此目的。
我的问题:
您是否选择目标信息'E'开始写'反向'...
SELECT
E.myTargetColumn
FROM
TblE E
INNER JOIN TblD D ON 1=1
INNER JOIN TblC C ON 1=1
INNER JOIN TblB B ON 1=1
INNER JOIN TblA A ON 1=1
WHERE
A.ID = myKnownInformation
...或者您选择以您已有的信息'A'开头?
SELECT
E.myTargetColumn
FROM
TblA A
INNER JOIN TblB B ON 1=1
INNER JOIN TblC C ON 1=1
INNER JOIN TblD D ON 1=1
INNER JOIN TblE E ON 1=1
WHERE
A.ID = myKnownInformation
两种设计都对我有意义。版本1,因为您直接选择所需的列。我不喜欢的是,你必须反思。
I need this Information, what do i need for that.
第二个版本对我来说也很有意义;您从所拥有的信息开始。我不喜欢它;您必须等到写入最后一个Join才能真正知道目标列的别名(E.myTargetColumn
)。
I have this information, how do i reach my target information?
1。这是什么标准?
2.两种设计的优缺点是什么?
补充问题;什么是JOIN的标准缩进?
答案 0 :(得分:3)
优化器并不关心,因为它会决定连接顺序本身,但为了便于阅读,我总是会从我的工作向前工作而不是向后工作。
select e.mytargetcolumn
from tbla a
join tblb b
on b.somekey = a.somekey
join tblc c
on c.somekey = b.somekey
join tbld d
on d.somekey = c.somekey
join tble e
on e.somekey = d.somekey
where a.id = myknowninformation
(这适用于内部联接。如果涉及外部联接,则联接顺序开始产生差异。)
这也适用于单个谓词,即使SQL解析器不关心 - 它是b.somekey = a.somekey
而不是a.somekey = b.somekey
,因为我们指定了b
的条件,与b.job = 'MINION'
和b.middle_name is null
。有关此问题的讨论,请参阅https://jonathanlewis.wordpress.com/2006/11/02/clarity-clarity-clarity及其评论。
至少在Oracle中,inner
和outer
关键字是可选的,不会添加任何信息,所以我认为它们是多余的,从不使用它们。
答案 1 :(得分:1)
决定在左连接上保留哪个表取决于您想要实现的目标。当table1中的连接条件的唯一值的数量与table2不同时,通常使用左连接。
例如 的表1:强>
| id | name|
+----+------+
| 1 | John |
| 2 | Bob |
| 3 | Brian|
<强>表2:强>
| id | subject| marks|
+----+------+------+
| 1 | History| 15 |
| 2 | Maths | 22 |
| 2 | History| 17 |
我会这样做
select Table1.name, sum(table2.marks) as total_marks --you will need to handle the null though
from table1
left join table2
on table1.id = table2.id
group by Table1.name;
基本上,包含所有行的表将首先位于不包含所有行的表的位置。
如果值的数量相同,那么您应该使用内部联接,顺序无关紧要。通常人们倾向于在开始时保持表中行数最多的表,否则将基表的类别保留在开头(即你的第二个例子),但这取决于你。
格式化是主观的,但根据我的经验,我将代码保持在同一级别,并在连接条件中略微缩进。例如
select a.column1 ,a.column2 ,a.column3 ,a.column4
,a.column5 , table1.column6 -- I indent this and add to the next line if there are lots of select items
-- I also keep the comma just before the column name so that if I want to comment it out the SQL code does not throw an error due to an extra comma in the previous line
from table1 --Same line because it is just one table
inner join
(
--Everything in here will be indented because it is an inner query
select * from --from is in the same line to save space, if there were selected columns it would be in the next line
table 2
where id = 1
) a
on table1.id = a.id --I like to indent the on criteria as it helps differentiate between tables, especially in a code like the one that you posted
and table1.name = a.name --multiple join criteria is just like multiple select columns
where tabl1.name = "Bob"
答案 2 :(得分:1)
您的查询都不比其他查询好。只需选择你喜欢的任何一个。
然而,仅仅考虑加入是一个常见的错误。加入,当您想要加入信息时。我们来看一个例子:
select p.product_name
from product p
join product_order po on po.product_id = p.product_id
where po.order_date > date '2017-04-01';
我们希望看到2017年4月1日之后订购的产品。但是,如果从那时起多次订购产品怎么办?然后我们会得到相同的产品多重。一个典型的“解决方案”是将其更改为select distinct p.product_name
,但是从一开始就只选择一个产品会更好。查询应该使用EXISTS
或IN
:
select product_name
from product
where product_id in
(select product_id from product_order where po.order_date > date '2017-04-01');
现在我们可以争辩你的查询最好是:
select mytargetcolumn
from e
where key1 in
(select key2 from d where key3 in
(select key4 from c where key5 in
(select key6 from b where key7 in
(select key8 from a where key9 = myKnownInformation)
)
)
)
在这个小例子中,这甚至是可读的。但在更复杂的情况下,所有这些子查询可能会令人困惑。另一种选择是:
select mytargetcolumn
from e
where key1 in
(
select d.key2
from d
join c on d.key3 = c.key4
join b on c.key5 = b.key6
join a on b.key7 = a.key8
where a.key9 = myKnownInformation
);
这两个查询中没有一个真的比其他查询“更好”。 (对于第二个查询,我们再次遇到表格顺序的“问题”,并想知道a.key9 = myKnownInformation
或where
中是否应该on
。)
所有这些实际上归结为:尽可能地将您的查询编写为可读。如果您认为from子句中的某个顺序比另一个更可读,那么请使用它。但请记住:也许你甚至不想加入: - )