左外连接不显示所有记录

时间:2016-01-14 23:22:01

标签: php mysql

我正在使用以下sql语句

SELECT * FROM inventory LEFT OUTER JOIN invUpdate ON (inventory.vin = invUpdate.vin)

它为我提供了正确的记录数,但仅显示来自invUpdate表的信息。我使用以下php变量

$row_Recordset1['vin']

显示基本网页上的记录。虽然它在页面下方列出了103条记录,但实际上只显示了invUpdate页面中的4条记录。其余的都是空的。我是否需要更改我的sql语句,还是应该使用其他变量?

2 个答案:

答案 0 :(得分:2)

我认为问题是查询返回了两列名为vin的列。并且这两者都被分配到相同的数组元素$row['vin']。我相信这是你遇到的问题的症结所在。

解决这个问题的一种方法是抛弃 SELECT * 并明确列出要返回的表达式。由于inventoryinvUpdate表都包含名为vin的列,因此这两个列都位于SELECT *返回的表达式列表中。

如果您需要返回两者,则使用别名分配这些表达式中的一个(或两个),以区别于另一个。例如:

SELECT inventory.vin               AS vin
     , inventory.somecol           AS somecol 
     , invUpdate.vin               AS uvin
     , SUBSTR(inventory.foo1,1,1)  AS f
     , ...
  FROM ...

获取一行后,您可以访问两个vin列返回的值,并通过指定的别名(即分配给表达式的列名称)引用它们。

  $val1 = $row['vin'];
  $val2 = $row['uvin'];

这不是唯一的方法。但它是我喜欢的方法,明确列出我想要返回的表达式,并明确指定别名。它是用于SQL语句中更复杂表达式的常用模式。同样的模式也适用于简单的陈述。

<强>后续

这远远超出了原来提出的问题。在回应评论时,关于&#34;覆盖&#34;当inventory中找到匹配的行时,来自invUpdate的列的值与invUpdate的列值相对应...

就个人而言,如果我想这样做,我宁愿在SQL语句中这样做。 (其他人有不同的意见,有不同意见的空间。我更喜欢有一个声明,返回我实际想要显示的结果,而没有很多额外的列。

不知道你的表格中有哪些列,(SELECT *并没有给那些可怜的读者留下太多信息),假设这两列中的列名相同。< / p>

鉴于连接谓词vin = vin,我们知道vin中的invUpdate在找到匹配的行时不能为NULL。

  SELECT IF(u.vin IS NULL,i.vin,u.vin) AS vin 

该表达式表示,如果在invUpdate中找不到匹配的行,则从vin表返回inventory,否则从vin表返回invUpdate 。这相当于更符合ANSI标准:

  SELECT CASE WHEN u.VIN IS NULL THEN i.vin ELSE u.vin END AS vin

如果我们需要来自invUpdate到&#34的列的所有的值,请覆盖&#34;来自inventory的所有列的值(当在invUpdate中找到匹配的行时,

  SELECT u.vin IS NOT NULL                     AS `update_found`
       , IF(u.vin IS NULL,i.vin    ,u.vin    ) AS `vin` 
       , IF(u.vin IS NULL,i.fee    ,u.fee    ) AS `fee`
       , IF(u.vin IS NULL,i.fi     ,u.fi     ) AS `fi`
       , IF(u.vin IS NULL,i.fo     ,u.fo     ) AS `fo`
       , IF(u.vin IS NULL,i.fum    ,u.fum    ) AS `fum`
       , u.updated_date                        AS `updated_date`
       , SUBSTRING(i.vin,1,5)                  AS `first_five`
    FROM inventory i
    LEFT
    JOIN invUpdate u
      ON u.vin = i.vin
    ORDER BY i.vin

是的,这是一个更复杂的SQL语句。但我可以测试一下。我可以验证它是否正常工作,返回我需要的集合,与程序的其余部分分开。这样我的程序中的代码就会少得多。

关注

问:让我说每张表中有32列。如果我想以这种方式展示它们,我是否必须为每列写入IF(u.id IS NULL,i.col,u.col)?

A:不幸的是,是的。

但是,如果我有32列要争用,我会编写一个SQL语句来获取我需要的SQL语句的一部分...使用SQL生成SQL。

作为一个单独的步骤(不是作为程序的一部分),来自mysql命令行客户端的SQLyog,或者其他......

我发表了类似这样的声明:

SELECT CONCAT('     , IF(u.vin IS NULL,i.`', c.column_name, '`,u.`', c.column_name, '`) AS `', c.column_name, '`') AS stmt
  FROM information_schema.columns c
 WHERE c.table_name   = 'mytable'
   AND c.table_schema = 'mydb'
 ORDER BY c.ordinal_position 

代替&#34; mytable&#34;和&#34; mydb&#34;使用表名和数据库名称,并返回如下结果:

stmt                                                                        
----------------------------------------------------------------------------
     , IF(u.vin IS NULL,i.`id`,u.`id`) AS `id`                             
     , IF(u.vin IS NULL,i.`ext_name`,u.`ext_name`) AS `ext_name`           
     , IF(u.vin IS NULL,i.`src_name`,u.`src_name`) AS `src_name`           
     , IF(u.vin IS NULL,i.`database_id`,u.`database_id`) AS `database_id`  
     , IF(u.vin IS NULL,i.`protocol`,u.`protocol`) AS `protocol`           
     , IF(u.vin IS NULL,i.`location`,u.`location`) AS `location`           
     , IF(u.vin IS NULL,i.`device_name`,u.`device_name`) AS `device_name`  
     , IF(u.vin IS NULL,i.`vendor_name`,u.`vendor_name`) AS `vendor_name`  
     , IF(u.vin IS NULL,i.`model_name`,u.`model_name`) AS `model_name`     

然后我会复制该结果,并将其粘贴到编辑器中,因此我不必输入所有这些列名。

答案 1 :(得分:0)

作为一种完全不同的方法...如果inventoryinvUpdate具有相同的列,列名,数据类型等,我们想要的是从{{1}返回所有行以及来自invUpdate的{​​{1}} ...

中没有匹配行的行

然后我们可以使用反连接模式从inventory返回行,然后将其(使用invUpdate)与来自{{1}的行合并}。

这样的事情:

inventory

两个查询的列数和数据类型(与UNION ALL结合使用)必须匹配。 (就匹配而言,列名称并不重要。结果集中列的名称来自第一个查询。)

这个答案没有具体解决所提出的问题;但我相信这是OP实际上想要的结果集。

与我之前的答案中的方法一样,这会将复杂性转移到SQL语句,从而大大简化了代码。

还有其他SQL模式(反连接除外)将返回等效结果。例如,使用UNION ALL谓词。例如,第一个查询(在invUpdate之前)也可以写成:

 ( SELECT i.vin
        , i.col2
        , i.col3
     FROM inventory i 
     LEFT
     JOIN invUpdate iu
       ON iu.vin = i.vin
    WHERE iu.vin IS NULL
 ) 
 UNION ALL
 ( SELECT u.vin
        , u.col2
        , u.col3
     FROM invUpdate u
 )
 ORDER BY vin

(我的偏好是反加入,除非我能从其他替代方案中获得更好的效果,例如NOT EXISTSUNION ALL

无论哪种方式,对于大型集合,缺少适当的索引都会对性能产生负面影响。