【问题标题】:How order by clause works in mysql, ordering shows wierd behaviourorder by 子句如何在 mysql 中工作,排序显示奇怪的行为
【发布时间】:2015-03-19 14:51:06
【问题描述】:

我有一个简单的查询

SELECT * FROM table_name order by non_unique_column LIMIT 0,50

这给了我按某种顺序排列的记录列表。

但是当我从表中删除* 并将some column names 放入时,它正在更改列表顺序。

对于some select 子句中的列组合,它给出了不同的顺序。

我找不到,select 子句中的列名模式给出了不同的顺序。

所以我想问有人遇到过这种问题吗?或者任何人都可以建议 order by 子句在这种情况下如何工作?

注意:如果我在 select 子句中添加所有列,它会得到与 * 相同的结果。

请随时提出任何可能的建议。

谢谢。

更新:此外,当我将 LIMIT 0,50 之类的限制条款更改为 LIMIT 0,15 时,我会得到不同的记录集。

更新2:

我已经创建了一个 sqlfiddle:

http://sqlfiddle.com/#!2/8f2340/3

请查看以下查询的结果

SELECT `M_ID`, `CON_FRST_NM`, `CON_PREFIX`, `CON_LST_NM`, `CON_MOB`,`CON_FAX` FROM `sample_table` order by `CON_PREFIX` LIMIT 0,60 

SELECT `M_ID`, `CON_FRST_NM`, `CON_PREFIX`, `CON_LST_NM`, `CON_MOB` FROM `sample_table` order by `CON_PREFIX` LIMIT 0,60 

查询的唯一区别是CON_FAX 不存在于第二个查询的选择子句中。

请帮我弄清楚为什么会出现这种差异。

还请查看以下使用不同限制子句的查询结果。 注意:这是上述查询中的第二个查询。

SELECT `M_ID`, `CON_FRST_NM`, `CON_PREFIX`, `CON_LST_NM`, `CON_MOB` FROM `sample_table` order by `CON_PREFIX` LIMIT 0,60 

SELECT `M_ID`, `CON_FRST_NM`, `CON_PREFIX`, `CON_LST_NM`, `CON_MOB` FROM `sample_table` order by `CON_PREFIX` LIMIT 0,15

谢谢。

个人意见: 我认为这是一个错误/缺陷,因为即使我没有定义任何唯一的 order by 子句并且 mysql 正在根据其计算应用一些随机排序,我觉得它不应该取决于 select 子句中的内容。我的问题是对于给定的记录集,无论我选择什么列,它都应该返回相同的有序记录。

【问题讨论】:

  • 不应该真的发生,我们可以看看一些示例数据吗?
  • 我确定不可能。
  • 简单规则 - 如果您想要一致的顺序,您必须使用ORDER BY 子句明确确定每一行的顺序。其他任何内容都只是实现细节,可能随时更改。
  • 所有ORDER BY 子句中的唯一列是CON_PREFIX。该列是否足以唯一确定所有行的顺序?不会。因此对于将交付的订单行没有没有保证。您观察不同的订单的事实只是进一步证明没有保证。而获得保证顺序的唯一方法是在ORDER BY 子句中添加更多列。
  • 这样说 - 根据查询的其他部分,数据库使用技术 A(可能使用一个特定的索引)或技术 B(可能累积结果并使用某种形式的哈希表) - 这些技术可能会产生不同顺序的结果。服务器then 使用您提供给它的关于您想要 的排序顺序的唯一信息,并执行产生该结果所需的最低限度的信息。其他任何东西都是浪费。

标签: mysql select sql-order-by


【解决方案1】:

这个问题是因为您为您的订单指定了一个重复的值,即先生或夫人。没有保证选择订单,因为他们都是先生或夫人。

如果您想确保它始终按特定顺序排列,那么您还应该将主键作为第二个顺序包含在内,以使其保持不变..又名

ORDER BY CON_PREFIX ASC, M_ID ASC

就目前而言,ORDER BY CON_PREFIX 正在给你它应该给你的东西,前缀按升序排列,没有什么与导致这种情况的限制有关,你只是没有告诉 MySQL 你还想要什么数据将返回给您。


回复您在问题中的PERSONAL OPINION 编辑...... 您所描述的内容是不合理的,这样想,任何用于提取数据的默认顺序现在都消失了,因为您指定了顺序。如果子句上没有任何 order by,则 mysql 有一个通用的选择模式,但一旦你在查询上设置 order by,这种模式又消失了

【讨论】:

  • 感谢回答,能否请您也看看limit相关的问题
  • 我做到了。你不明白我在回答中所说的吗?
  • 我明白你在说什么。由于我已将 CON_PREFIX 定义为我的非唯一顺序,因此 my_sql 给出了一些随机顺序,即Acceptable behaviour。现在,如果我将 select 子句从仅选择单个列或所有列更改,它应该为我提供有序记录,而不管我的 select 子句如何。
  • @NamanGala 你不能保证它与相同的列相同......如果你多次运行选择它可能会不同,或者mysql可能在内存中使用相同的选择来返回结果,但是事实是,如果您连续 10 次运行这些查询中的任何一个,您无法确保它是相同的
  • 让我尝试一个查询 10 次,然后检查结果是否发生变化。
【解决方案2】:

order by 子句从左到右
举个例子吧

如果你使用 SELECT serialNo,Name FROM table_name order by serialNo,Name;

这是做什么的,它会在第一个实例中订购 serialNo ,然后在第二个实例中订购 Name 。当它在第二个实例中订购 name 时,serialNo 的顺序将根据 name 的顺序发生变化。

希望我的解释清楚。

【讨论】:

  • 不正确,如果您指定要排序的特定列,则不会有额外的排序会导致原始列倾斜
  • 请为我的回答投下一些光。
  • @JohnRuddell 那么您认为我的查询将如何工作?我的查询的排序依据是什么?
  • 这取决于您在 order by 中指定的列.. OP 说 non_unique_column,让我们说在您的查询中是 Name,然后 ORDER BY Name 将返回所有行名称按字母升序排列,因为这是默认值
  • 现在通过您的编辑,我可以看到您确实错过了问题的重点。问题是仅一列不超过一列的 ORDER BY。
猜你喜欢
  • 1970-01-01
  • 2021-10-11
  • 2017-12-07
  • 2016-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多