使用OUTER JOIN时缺少列数据

时间:2014-11-10 06:41:21

标签: mysql outer-join mariadb

在我开始之前;这不是你正常的MySQL JOIN问题......好吧,尽管我不知道基本的JOIN问题。

基本上我的问题归结为我正在运行的查询,尽管存在数据,但它似乎并未返回所有外部连接。奇怪的是,如果我使用内连接,则返回数据;如果我使用汇总函数(使用外连接时),也会返回数据。

我们正在运行MariaDB:

mysqld --version
mysqld  Ver 10.0.12-MariaDB-1~wheezy-log for debian-linux-gnu on x86_64 (mariadb.org binary distribution)

我已经能够在一个更简单的查询中复制问题,我将在下面详细介绍(简单的票证/交易表和客户/卡表):

表格如下:

-------------------
|CUSTOMER         |
-------------------
|*card_number     |
-------------------

-------------------
|TICKET           |
-------------------
|*id              |
|card_number      |
|transaction_value|
-------------------

第一个查询正在使用常规外部联接,它返回所有销售(包括非卡销售)。这是我想要收到的数据,但是如果查看返回的值,则票证ID 8没有附加卡号(即使计数字段表示已找到它)。

SELECT ticket.id,
       ticket.transaction_value,
       customer.card_number,
       COUNT(customer.card_number)
  FROM ticket
       LEFT OUTER JOIN customer ON ticket.card_number = customer.card_number
 WHERE DATE(ticket.timestamp) = "2014-11-09"
 GROUP BY ticket.id;

 id, transaction_value, card_number, count
 4 , 205.13           , {null}     , 0
 5 , 116.04           , xxx4785    , 1
 6 , 74.97            , xxx0281    , 1
 7 , 19.99            , xxx6836    , 1
 8 , 55.98            , {null}     , 1
 9 , 13.59            , {null}     , 0

第二个查询使用内部联接,该联接仅返回附有卡片的销售,但在这种情况下,我们可以看到故障单8现在具有卡号。为什么它没有出现在第一个查询中?

SELECT ticket.id,
       ticket.transaction_value,
       customer.card_number,
       COUNT(customer.card_number)
  FROM ticket
       JOIN customer ON ticket.card_number = customer.card_number
 WHERE DATE(ticket.timestamp) = "2014-11-09"
 GROUP BY ticket.id;

id, transaction_value, card_number, count
 5, 116.04           , xxx4785    , 1
 6, 74.97            , xxx0281    , 1
 7, 19.99            , xxx6836    , 1
 8, 55.98            , xxx0273    , 1

最后我决定尝试使用汇总功能:在这种情况下,我再次使用外部联接,发现票证8再次附加了卡号。我重复了MIN并得到了相同的结果。

 SELECT ticket.id,
       ticket.transaction_value,
       MAX(customer.card_number),
       COUNT(customer.card_number)
  FROM ticket
       LEFT OUTER JOIN customer ON ticket.card_number = customer.card_number
 WHERE DATE(ticket.timestamp) = "2014-11-09"
 GROUP BY ticket.id;

 id, transaction_value, card_number, count
 4 , 205.13           , {null}     , 0
 5 , 116.04           , xxx4785    , 1
 6 , 74.97            , xxx0281    , 1
 7 , 19.99            , xxx6836    , 1
 8 , 55.98            , xxx0273    , 1
 9 , 13.59            , {null}     , 0

有人可以了解这里发生的事情吗?我真的希望能够解决这个问题,而不必诉诸复杂的解决方案,如多个查询或添加特殊的汇总函数等。(在发生这种情况之前,外连接的情况很好)。

2 个答案:

答案 0 :(得分:1)

看起来我可能找到了罪魁祸首; Maria 10.x中存在一个错误,当使用group by MariaDB Bug Report时,会导致外连接中省略结果。感谢Aziz提出了一些很好的建议并帮助我。希望这可能会帮助那些和我一样困惑的人!

更新:我测试了MariaDB 10.0.21并确认错误已经修复。

答案 1 :(得分:0)

您正在GROUP BY上执行ticket.id,但您的SELECT列表也包含非ticket.transaction_value, customer.card_number的非分组列。这导致数据不一致。传统上(在其他RDBMS服务器中)这会产生语法错误,但是MySql允许它,因此查询编写者必须确保他们自己处理这种情况。

参考:http://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html

  

在标准SQL中,包含GROUP BY子句的查询不能引用选择列表中未在GROUP BY子句中命名的非聚合列。

     

MySQL扩展了GROUP BY的使用,因此选择列表可以引用未在GROUP BY子句中命名的非聚合列。

     

服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选的值是不确定的。