【问题标题】:Perform a left join with a second table after an inner join (on same table) after where conditions (Mysql)在 where 条件(Mysql)之后的内部联接(在同一个表上)之后与第二个表执行左联接
【发布时间】:2015-07-07 11:17:17
【问题描述】:

这是我的数据库:bott_no_mgmt_data

random_no ; company_id ; bottle_no ; date       ; returned ; returned_to_stock ; username
    30201 ; MY COMP    ;         1 ; 2015-04-28 ;       10 ; NULL              ; ANDREW
    30202 ; MY COMP    ;         2 ; 2015-04-28 ;       10 ; NULL              ; ANDREW
    30205 ; MY COMP    ;         5 ; 2015-04-28 ;       10 ; NULL              ; ANDREW
    30208 ; MY COMP    ;         8 ; 2015-04-28 ;       10 ; NULL              ; ANDREW
    30209 ; MY COMP    ;         9 ; 2015-04-28 ;       10 ; NULL              ; ANDREW
    30210 ; MY COMP    ;        10 ; 2015-04-28 ;       10 ; NULL              ; ANDREW
    30211 ; MY COMP    ;         1 ; 2015-04-29 ;       20 ; NULL              ; ANDREW
    30212 ; MY COMP    ;         2 ; 2015-04-29 ;       20 ; NULL              ; ANDREW
    30213 ; MY COMP    ;         9 ; 2015-04-29 ;       30 ; NULL              ; ANDREW
    30214 ; MY COMP    ;        10 ; 2015-04-29 ;       30 ; NULL              ; ANDREW

我已成功从bott_no_mgmt_data 中提取所有唯一行,其中random_no 字段最高,bottle_no 是唯一的,代码如下:

select yt.* 
  from bott_no_mgmt_data yt<br>
       inner join(select bottle_no, max(random_no) random_no
                    from bott_no_mgmt_data 
                   WHERE username = 'ANDREW' 
                   group by bottle_no) ss on yt.bottle_no = ss.bottle_no 
                                         and yt.random_no = ss.random_no  
where returned < 15 and date > '2015-04-01'

因此,例如它返回的行之一将是

30214;MY COMP;10;2015-04-29;30;NULL;ANDREW 

而不是

30210;MY COMP;10;2015-04-28;10;NULL;ANDREW

因为虽然它们的bottleno 相同,但前者的 random_no 更高。

我的问题:

我现在希望将每个返回的行 'bottleno' 与另一个表 'sample' 进行比较,该表仅包含字段 'bottleno' 和瓶号列表。我希望比较它们并且只返回那些匹配的。我假设我们然后将上面的结果与数据库'sample''LEFT JOIN'如下:

select yt.* from bott_no_mgmt_data yt<br>
       inner join(select bottle_no, max(random_no) random_no
                    from bott_no_mgmt_data WHERE username = 'ANDREW' 
                   group by bottle_no) ss on yt.bottle_no = ss.bottle_no and yt.random_no = ss.random_no 
 where returned < 15 and date > '2015-04-01'
       LEFT JOIN sample ON sample.bottleno = yt.bottle_no

额外的左连接给我一个错误

1064 - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 7 行的“LEFT JOIN sample ON sample.bottleno = yt.bottleno WHERE sample.bottleno IS NULL”附近使用正确的语法

【问题讨论】:

  • WHERE 子句之后执行左连接。
  • 谢谢Dan,但它肯定必须在where子句之后吗?仅在使用 where 原因查询表 A 后,我才比较表 A 和表 B 的结果?
  • 您的原始查询返回第 30205 和 30208 行

标签: php mysql join


【解决方案1】:

有几件事。您根本不需要第一个内部连接,这是没有意义的。另外,您说“我希望比较它们并只返回匹配的那些。” - 这意味着你想要 INNER JOIN 而不是 LEFT JOIN。

SELECT MAX(random_no) AS random_no, company_id, yt.bottle_no, `date`, returned, username
FROM bott_no_mgmt_data yt
INNER JOIN sample ON sample.bottle_no=yt.bottle_no
WHERE yt.username = 'ANDREW' 
  AND yt.returned < 15 
  AND yt.date > '2015-04-01'
GROUP BY company_id, yt.bottle_no, `date`, returned, username

【讨论】:

  • 这不是没有意义的。 "SELECT yt.*" 必须工作。
  • @Strawberry 真实数据。我想使用连接比指定 SELECT 和 GROUP BY 子句中的所有列更容易,但我敢打赌它效率不高。
  • 在 SELECT 和 GROUP BY 子句中指定所有列将不起作用。在可行的各种解决方案中,OP 的解决方案可能是最有效的。这是一个标准的不相关子查询,如手册中所述,在其他地方也有令人作呕的
  • 根据 OP 规范,正确的行是 30205 和 30208。也就是说,关于 OP 的 OUTER JOIN 的另一点是正确的。在这种情况下,OUTER JOIN 是没有意义的,因为不需要该连接表中的列。
  • @Strawberry 我看到了问题以及这与 OP 的帖子之间的逻辑差异 - 感谢您花时间帮助我理解它。
【解决方案2】:

正如 Daan 所说,所有连接都应该写在 Where 子句之前:

select yt.* from bott_no_mgmt_data yt
inner join(
    select bottle_no, max(random_no) random_no 
    from bott_no_mgmt_data 
    WHERE username = 'ANDREW' group by bottle_no
)
ss on yt.bottle_no = ss.bottle_no and yt.random_no = ss.random_no 
LEFT JOIN sample ON sample.bottleno = yt.bottle_no
where returned < 15 and date > '2015-04-01'

【讨论】:

  • cDima,谢谢,快速查询示例数据库中是否有 3 个匹配项(具有相同的bottleno/bottle_no)它返回 3 行,但是如果没有匹配项,它仍然返回单行?没有可能匹配时返回一行的任何可能原因?
  • 取决于源数据;在没有结果的情况下,内部分组选择是否返回任何内容?也许制作 INNER LEFT 会删除空结果 - stackoverflow.com/questions/5706437/…
猜你喜欢
  • 2019-02-23
  • 2011-05-07
  • 1970-01-01
  • 1970-01-01
  • 2018-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多