左外连接产生意外结果

时间:2018-09-16 17:14:57

标签: mysql left-join

我正在做一个简单的查询:

fun main(args: Array<String>) {
    Application.launch(HelloWorldApp::class.java, *args)
}

class HelloWorldApp : App(HelloWorld::class)

class HelloWorld : View() {
    override val root = hbox {
        addEventFilter(KeyEvent.ANY) { event ->
            println("pressed:"+event.character)
        }
    }
}

按预期方式,返回了Bench表的所有行,但是如果我尝试获取B_id字段,我发现该字段已设置为NULL。 然后,我尝试了另一个应该完全等效的查询:

SELECT * FROM Bench LEFT JOIN  ASSIGNED_DOM 
        ON (Bench.B_id=ASSIGNED_DOM.B_id)  WHERE Bench.B_type=0 ;

但是在这种情况下,B_id字段会正确返回。 第一个查询出了什么问题?两者之间有什么区别?

2 个答案:

答案 0 :(得分:1)

如果列名相同,则第二个表中的值将覆盖第一个表中的值。尝试在查询中使用别名

SELECT Bench.B_id AS bid1, ASSIGNED_DOM.B_id AS bid2 
FROM Bench 
LEFT JOIN  ASSIGNED_DOM ON (Bench.B_id=ASSIGNED_DOM.B_id) 
WHERE Bench.B_type=0;

答案 1 :(得分:1)

这两个查询是等效的。根据{{​​3}}

  

自然联接和使用USING的联接,包括外部联接变体,均根据SQL:2003标准进行处理。

     

NATURAL联接的冗余列不出现

这具体归结为以下差异:

  

USING子句可以重写为比较相应列的ON子句。但是,尽管USING和ON相似,但是它们并不完全相同。

     

关于确定哪些行满足连接条件,两个连接在语义上是相同的。

     

关于确定要为SELECT *扩展显示哪些列,两个联接在语义上并不相同。 USING联接选择相应列的合并值,而ON联接则选择所有表格中的所有列

因此,您的第一个查询有两列同名bench.B_id, ASSIGNED_DOM.B_id,而第二个查询只有一列coalesce(bench.B_id, ASSIGNED_DOM.B_id) as B_id

如何正确处理第一种情况取决于您的应用程序/框架。例如。 MySQL客户端或phpmyadmin将仅显示所有列。某些框架可能会以某种方式更改名称,以使其唯一。

特别是

php(我假设您正在使用它)不会:如果使用$row['B_id'],它将返回最后一次出现(尽管未指定行为),因此在情况下,您将得到ASSIGNED_DOM.B_id。不过,您仍然可以访问两个具有索引的列(例如$row[0]$row[1]),但只能访问具有相同列名的列中的一个。

为防止此类问题,您可以/应该使用别名,例如select bench.B_id as bench_B_id, ASSIGNED_DOM.B_id as ASSIGNED_DOM_B_id, ...