【问题标题】:Order By Ignores Fourth Character排序方式忽略第四个字符
【发布时间】:2016-12-11 08:37:58
【问题描述】:

我有一个包含以下值的表,在路径列上有一个索引。当我选择按路径排序的值时,它使用索引,但忽略第三个之后的任何数字。见下文。

我得到了什么:

category_id name                    path
1091        Bagels and Donuts       114.1091 (1 is ignored)
1092        Barbecue                114.1092 (2 is ignored)
115         Afghan Restaurant       114.113
1140        International           114.1140 (0 is ignored)
116         African Restaurant      114.116 
117         Ethiopian Restaurant    114.116.117
118         American Restaurant     114.118
119         New American Restaurant 114.118.119
120         Asian Restaurant        114.120

我应该得到什么:

category_id name                    path
115         Afghan Restaurant       114.113
116         African Restaurant      114.116 
117         Ethiopian Restaurant    114.116.117
118         American Restaurant     114.118
119         New American Restaurant 114.118.119
120         Asian Restaurant        114.120
1091        Bagels and Donuts       114.1091
1092        Barbecue                114.1092
1140        International           114.1140

有什么想法吗?

【问题讨论】:

  • 您确定索引没有按预期工作吗?您当前的订单对我来说很合适。
  • @TimBiegeleisen 顶部的结果是我得到的,底部的结果是应该的
  • 排序作为字符串是正确的。您的预期是数字,这是不同的。然而它仍然是可以实现的。再试试你的大脑:D
  • 我不认为他们“应该”像底部一样。我认为他们应该像顶部一样。
  • 按数据类型字符串排序产生输出“上方”,按数据类型数字排序产生“底部”输出。如果要实现底部的输出,请将路径转换为数值,然后重试。或者这可以帮助你:stackoverflow.com/a/2542021/1809168

标签: mysql innodb


【解决方案1】:

假设你的路径中只有 3 个部分:

SELECT * FROM tab
ORDER BY
  substring_index(path, '.',  1) + 0, ## sort by 1st part
  substring_index(substring_index(path, '.', 2), '.' , -1) + 0, ## sort by 2nd part
  substring_index(path, '.', -1) + 0 ## sort by 3rd part

想象一下这不是IP,否则是一种更简单的方法。

【讨论】:

    【解决方案2】:

    这是我的最终解决方案。将每个级别放入其自己的 INT 列中,然后为所有列创建一个索引。感谢大家的大力投入。

    DELIMITER $$
    DROP FUNCTION IF EXISTS SPLIT_STR; $$
    CREATE FUNCTION SPLIT_STR(
      x VARCHAR(255),
      delim VARCHAR(12),
      pos INT
    )
    RETURNS VARCHAR(255)
    RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
           LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
           delim, '');$$
    
    DROP FUNCTION IF EXISTS GetLevel; $$
    CREATE FUNCTION GetLevel (path VARCHAR, LevelN INT) RETURNS VARCHAR(1024)
    DETERMINISTIC
    BEGIN
        DECLARE str VARCHAR(255);
    
        SET str = SPLIT_STR(path,".",levelN);
        IF str='' THEN
            RETURN NULL;
        END IF;
    
        RETURN str;
    
    END $$
    DELIMITER ;
    
    UPDATE categories SET level1 = GetLevel(category_id, 1), level2 = GetLevel(category_id, 2), level3 = GetLevel(category_id, 3), level4 = GetLevel(category_id, 4), level5 = GetLevel(category_id, 5);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-24
      • 1970-01-01
      • 2014-06-05
      • 1970-01-01
      • 2014-01-20
      • 2018-09-21
      • 1970-01-01
      • 2015-10-04
      相关资源
      最近更新 更多