【问题标题】:MySQL - JOIN only if a row exists from the left tableMySQL - 仅当左表中存在一行时才加入
【发布时间】:2012-12-20 09:28:34
【问题描述】:

这里是 MySQL:

SELECT  a.id,
        a.name,
        a.n,
        a.r,
        a.pot,
        a.ticket_price,
        a.starting_tickets,
        a.started,
        a.end,
        COUNT(b.id) tickets_bought 
FROM current_lotteries a
   JOIN lottery_tickets b ON b.lid=a.id
WHERE a.cid=1 
ORDER BY started DESC LIMIT 1    

在搜索中,如果a 中没有行,但b 中有行(即COUNT(b.id) 不是NULL),则此查询返回NULL 值为a 的行字段以及 COUNT(b.id) 的任何值作为 tickets_bought。如果表 a 中没有结果,如何修改此查询使其不返回行 (num_rows = 0)?

一个快照。

【问题讨论】:

  • 不,tickets_bought 是别名。
  • “此查询返回一行,a 字段为 NULL 值”我不同意,除非 a 本身可以包含 NULL 值。
  • 这真的是您使用的查询吗?您描述的行为不是INNER JOIN 的行为,而是RIGHT JOIN 的行为
  • 我检查了表结构,NULL 下的每一列都有no。但是当我运行上述查询时,它会为每个字段返回NULL
  • 等等,我想我明白了 - 没有 GROUP BY,而且 MySQL 经常将自己与聚合混淆。

标签: mysql select join group-by


【解决方案1】:

没有GROUP BY 子句,MySQL(它允许在其他RDBMS 中出现错误的情况下这样做)在应该对它们进行分组时将聚合组应用于b 中的所有行。添加GROUP BY a.id

SELECT  a.id,
        a.name,
        a.n,
        a.r,
        a.pot,
        a.ticket_price,
        a.starting_tickets,
        a.started,
        a.end,
        COUNT(b.id) tickets_bought 
FROM current_lotteries a
   JOIN lottery_tickets b ON b.lid=a.id
WHERE a.cid=1 
GROUP BY a.id
ORDER BY started DESC LIMIT 1    

以上内容适用于 MySQL,但不适用于其他地方。更便携的版本使用相关子查询:

SELECT  a.id,
        a.name,
        a.n,
        a.r,
        a.pot,
        a.ticket_price,
        a.starting_tickets,
        a.started,
        a.end,
        b.tickets_bought
FROM current_lotteries a
        /* More portable to join against a subquery which returns the count per group */
        JOIN (
            SELECT b.lid, COUNT(*) AS tickets_bought 
            FROM lottery_tickets 
            GROUP BY lid
        ) b ON a.id = b.lid
WHERE a.cid = 1
ORDER BY started DESC LIMIT 1

【讨论】:

  • 我按b.lid分组了,好像可以,有什么区别?
  • @KeirSimmons 在那个版本中,没有区别,因为它是一个内部连接。我发布的第二个查询更合适,因为它不依赖于奇怪的 MySQL 行为。
  • @KeirSimmons:如果没有GROUP BY,它将计算您的查询返回的所有行。但从查询中可以明显看出,您希望按a.id 计数。这就是您需要按该标准指定 分组 的原因,这会影响 COUNT() 的结果。
【解决方案2】:

试试这个:

SELECT a.id, a.name, a.n, a.r, a.pot, a.ticket_price, 
       a.starting_tickets, a.started, a.end, b.tickets_bought 
FROM current_lotteries a 
RIGHT JOIN (SELECT b.lid, COUNT(*) AS tickets_bought 
            FROM lottery_tickets GROUP BY lid ) b ON a.id = b.lid 
WHERE a.cid = 1 
ORDER BY started DESC 
LIMIT 1;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    • 2016-10-19
    • 2017-10-08
    • 2013-09-11
    • 1970-01-01
    相关资源
    最近更新 更多