MySQL ORDER BY奇怪的排序

时间:2014-06-04 16:16:21

标签: mysql sorting sql-order-by

问题:mysql查询返回结果奇怪的顺序,看起来像是随机的。但它只发生在一个托管,localhost和另一个托管运作良好。想知道 - 为什么会发生以及如何防止它。

架构:

CREATE TABLE `product` (
  `product_id` int(11) NOT NULL AUTO_INCREMENT,
  `sort_order` int(11) NOT NULL DEFAULT '0',
  `status` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`product_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

insert into product (sort_order, status)
values
(0, 1),
(0, 1),
(0, 1),
(0, 1),
(0, 1);

CREATE TABLE `product_description` (
  `product_id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`product_id`),
  KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

insert into product_description
values
(1, 'product_1'),
(2, 'product_2'),
(3, 'product_3'),
(4, 'product_4'),
(5, 'product_5');

CREATE TABLE `product_to_category` (
  `product_id` int(11) NOT NULL,
  `product_category_id` int(11) NOT NULL,
  PRIMARY KEY (`product_id`,`product_category_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

insert into product_to_category
values
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(5, 1);

CREATE TABLE `product_category_path` (
  `product_category_id` int(11) NOT NULL,
  `path_id` int(11) NOT NULL,
  `level` int(11) NOT NULL,
  PRIMARY KEY (`product_category_id`,`path_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

insert into product_category_path values (1, 1, 0);

查询:

SELECT p.product_id, pc.product_category_id, pd.name
    FROM `product` p
        LEFT JOIN `product_description` pd ON pd.product_id = p.product_id
        LEFT JOIN `product_to_category` pc ON pc.product_id = p.product_id
    WHERE p.status = 1 AND pc.product_category_id IN (SELECT product_category_id FROM `product_category_path` WHERE path_id = 1)
    ORDER BY p.sort_order ASC;

在localhost和托管结果总是相同的:1,2,3,4,5。但在托管它显示1,3,2,5,4或2,1,5,3,4和每次新订购。为什么呢?

更新

http://dev.mysql.com/doc/refman/5.5/en/order-by-optimization.html

http://s.petrunia.net/blog/?p=24

1 个答案:

答案 0 :(得分:2)

允许SQL系统(任何品牌和型号)以他们认为方便的任何顺序返回结果集行,除非您专门指定订单。换句话说,除非在ORDER BY中指定,否则结果集的顺序正式无法预测。换句话说,在localhost服务器上,您的结果按照您认为应该处于的顺序完全是偶然的。表没有固有的顺序。

您真的很幸运,您的生产服务器如此迅速地在您的查询中暴露了这个缺陷。开发人员通常不会发现这些东西,直到他们的表格增长到数万行。

由于您的查询修改显示(http://sqlfiddle.com/#!2/211536/2/0),因此结果集中的所有行都具有相同的SORT_ORDER值。

<强>查询

SELECT p.sort_order, p.product_id, pc.product_category_id, pd.name
    FROM `product` p
        LEFT JOIN `product_description` pd ON pd.product_id = p.product_id
        LEFT JOIN `product_to_category` pc ON pc.product_id = p.product_id
    WHERE p.status = 1 AND pc.product_category_id IN (SELECT product_category_id FROM `product_category_path` WHERE path_id = 1)
    ORDER BY p.sort_order ASC

<强>结果:

| SORT_ORDER | PRODUCT_ID | PRODUCT_CATEGORY_ID |      NAME |
|------------|------------|---------------------|-----------|
|          0 |          1 |                   1 | product_1 |
|          0 |          2 |                   1 | product_2 |
|          0 |          3 |                   1 | product_3 |
|          0 |          4 |                   1 | product_4 |
|          0 |          5 |                   1 | product_5 | 

你已经告诉SQL以这种方式订购它们。两台服务器都这样做了。

如果您需要PRODUCT_ID以及SORT_ORDER订购它们,请指定它(http://sqlfiddle.com/#!2/211536/4/0)。

    ORDER BY p.sort_order ASC, p.product_id ASC;