【问题标题】:mysql select field determines order of result setmysql 选择字段确定结果集的顺序
【发布时间】:2018-03-20 11:22:57
【问题描述】:

我的一个 mysql 5.6 查询目前正在经历(对我而言)非常奇怪的行为。

我有一个正在尝试优化的给定系统。一个步骤是只选择下一个操作所需的字段。

给定的查询如下所示:

SELECT oxv_oxcategories_6_fr.*
FROM oxv_oxobject2category_6 AS oxobject2category
  LEFT JOIN oxv_oxcategories_6_fr ON oxv_oxcategories_6_fr.oxid = 
oxobject2category.oxcatnid
WHERE oxobject2category.oxobjectid = '<hashed id>'
  AND oxv_oxcategories_6_fr.oxid IS NOT NULL
  AND (oxv_oxcategories_6_fr.oxactive = 1
       AND oxv_oxcategories_6_fr.oxhidden = '0')
ORDER BY oxobject2category.oxtime

我冒昧地在自己的查询中使用更合理的命名:

SELECT
  category_view.*
FROM oxv_oxobject2category_6 category_mapping_view
  LEFT JOIN oxv_oxcategories_6_fr category_view ON category_view.OXID = 
category_mapping_view.OXCATNID
WHERE category_mapping_view.OXOBJECTID = '<hashed id>'
  AND category_view.OXID IS NOT NULL
  AND (category_view.OXACTIVE = 1
       AND category_view.OXHIDDEN = '0')
ORDER BY category_mapping_view.OXTIME

如您所见,没有太大区别,只是命名不同。到目前为止,一切都按预期工作。现在我试图只选择我需要的值。所以查询看起来像这样:

SELECT
  category_view.OXID,
  category_view.OXTITLE
FROM oxv_oxobject2category_6 category_mapping_view
  LEFT JOIN oxv_oxcategories_6_fr category_view ON category_view.OXID = 
category_mapping_view.OXCATNID
WHERE category_mapping_view.OXOBJECTID = '<hashed id>'
  AND category_view.OXID IS NOT NULL
  AND (category_view.OXACTIVE = 1
       AND category_view.OXHIDDEN = '0')
ORDER BY category_mapping_view.OXTIME;

这也可以按预期工作。但是,我还需要字段 OXPARENTID,所以我将 SELECT 语句更改为

category_view.OXID,
category_view.OXTITLE,
category_view.OXPARENTID

现在项目的顺序不同了,我似乎无法找出原因。新查询和原始查询都对 OXTIME 进行排序,但最终结果集中没有该字段。大约有 10 个条目,其中 OXTIME 为 0,并且当我查询 OXPARENTID 时,这些条目就会被翻转(按顺序排列)。

在原始查询中,OXPARENTID 也存在,那么为什么它现在有所作为?我猜有某种我还不知道的排序逻辑正在发生。

请注意,两个连接表实际上都是视图,也许这与它有关。此外,OXIDOXPARENTID 都是 md5 哈希值。

任何帮助将不胜感激。

编辑

为了澄清,我知道多个条目的 OXTIME 等于 0 的事实使得无法事先预测哪个条目将是顶部的条目。但是,我仍然希望每次调用查询时条目的顺序都相同(无论我选择什么)。

一个答案 (@GordonLinoff) 解释说,

[...] 相同的查询可以在不同的运行中以不同的顺序返回结果

这种“随机性”从何而来?

【问题讨论】:

  • ` AND (category_view.OXACTIVE = 1 AND category_view.OXHIDDEN = '0')` - 这是一个内部连接
  • sql中没有隐式顺序。您仅按 oxtime 排序,因此其他字段(具有相同 oxtime)将具有随机顺序。为什么不直接将其他字段添加到您的订单中?
  • @AlexZen 不幸的是,目前两个系统(旧的和新的)都必须返回相同的结果。尽我所能,目前我无法改进该查询的顺序。

标签: mysql sql oxid


【解决方案1】:

您的订单是:

ORDER BY category_mapping_view.OXTIME;

然后你说:

大约有 10 个 OXTIME 为 0 的条目,当我查询 OXPARENTID 时,这些条目就会被翻转(按顺序排列)。

你所拥有的是钥匙中的纽带。结果可以按任何顺序排列——同一个查询可以在不同的运行中以不同的顺序返回结果。从技术上讲,SQL 中的排序是不稳定的

您可以通过在ORDER BY 中包含另一列来解决此问题,这样每一行都由ORDER BY 键唯一定义。也许那是OXID

ORDER BY category_mapping_view.OXTIME, category_view.OXID;

顺便说一句,SQL 中的排序是不稳定的,这是“显而易见的”。为什么? SQL 表代表 无序 集合。当键相同时,没有顺序可以回退。

【讨论】:

  • 感谢您的回答。您能否对mysql如何对其结果进行排序有所了解?我知道这个查询远非完美,但不幸的是我无法更改该排序。但我仍然有这样的印象,如果我多次运行相同的查询,我会得到相同的返回结果(实际上就是这样)。怎么回事,即使是同一个查询,mysql 也可能将排序从一个查询更改为下一个查询?
  • @Micha 。 . .当键相同时排序是不稳定的——因为 SQL 表代表 unordered 集合。您可以很好地“稳定排序”以更好地理解这意味着什么。
猜你喜欢
  • 2016-11-26
  • 2017-02-05
  • 1970-01-01
  • 2013-01-31
  • 1970-01-01
  • 2021-08-23
  • 2013-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多