【问题标题】:MySQL order by mixed ASC/DESC in the same columnMySQL 在同一列中按混合 ASC/DESC 排序
【发布时间】:2014-06-20 19:08:15
【问题描述】:

我正在尝试按同一列中的 ASC 和 DESC 顺序对数据库中的产品仓位进行排序,以允许仓库拣货员穿过仓库岛拣货。换句话说,当一个拣货员从仓库拿到一批订单要拣货时,系统需要从 1 号岛的前面开始拣货,然后从该岛到终点进行拣货。然后它会将他们跳过到 2 号岛的末端(而不是开始),然后他们会朝着 2 号岛的前面前进,然后从 3 号岛的前面开始,依此类推。

bin 位置的格式为:ISLE - BAY - SHELF - SLOT/BIN 以下是要选择的 bin 位置的示例数据表:

  • 1-0-A-01
  • 1-1-D-06
  • 1-2-E-10
  • 1-2-E-11
  • 1-10-A-01
  • 2-1-D-02
  • 2-1-C-12
  • 2-5-F-01
  • 3-5-A-12
  • 3-6-D-01
  • 4-5-A-02
  • 4-5-A-03
  • 4-5-B-10

我需要执行 SQL 查询并拉取位置并像这样对它们进行排序:

  • 1-0-A-01
  • 1-1-D-06
  • 1-2-E-10
  • 1-2-E-11
  • 1-10-A-01
  • 2-5-F-01
  • 2-1-D-02
  • 2-1-C-12
  • 3-5-A-12
  • 3-6-D-01
  • 4-5-B-10
  • 4-5-A-03
  • 4-5-A-02

是否可以仅使用 SQL 查询来做到这一点?

【问题讨论】:

  • 如果这些坐标是 text/varchar 字段中的字符串,那么不,没有可以运行的简单查询来正确排序它们。您需要对 DB 进行规范化,以便每个坐标组件都在其 OWN 字段中,然后一个简单的 order by isle, bay, shelf, slot 将满足您的需求。
  • 您可以尝试按各自的部分订购:Order by SUBSTRING_INDEX(SUBSTRING_INDEX(yourColumn, '-', 1), ' ', -1), SUBSTRING_INDEX(SUBSTRING_INDEX(yourColumn, '-', 2), ' ', -1), ... 等。但这可能会很慢
  • 这是一个varchar字段。

标签: mysql sql sql-order-by


【解决方案1】:

是的,这可以在 SQL 查询中完成,尽管语法很重要。

您首先需要表达式将 ISLE-BAY-SHELF “拆分”为单独的组件,然后在 ORDER BY 子句中使用这些表达式。

对于MySQL

一些示例表达式,放入 SELECT 列表中,以便我们查看它们返回的内容:

SELECT SUBSTRING_INDEX('1-10-A-01','-',1)+0 AS ISLE
     , SUBSTRING_INDEX(SUBSTRING_INDEX('1-10-A-01','-',2),'-',-1)+0 AS BAY
     , SUBSTRING_INDEX(SUBSTRING_INDEX('1-10-A-01','-',3),'-',-1) AS SHELF
     , SUBSTRING_INDEX('1-10-A-01','-',-1)+0 AS `SLOT/BIN`

这些表达式基于始终存在三个破折号的假设,并且始终采用 numeric-numeric-whatever-numeric 格式。

给定样本数据,我们可以检查 ISLE 组件是偶数还是奇数,然后根据它对 BAY 进行升序或降序排序。但这可能不是您想要的,如果跳过一个过道,如果我们完全跳过过道 2,只做过道 1 和 3。

CREATE TABLE ibss (ibss VARCHAR(20));
INSERT INTO ibss (ibss) VALUES 
('1-0-A-01')
,('1-1-D-06')
,('1-2-E-10')
,('1-2-E-11')
,('1-10-A-01')
,('2-5-F-01')
,('2-1-D-02')
,('2-1-C-12')
,('3-5-A-12')
,('3-6-D-01')
,('4-5-B-10')
,('4-5-A-03')
,('4-5-A-02');


SELECT i.ibss
     , SUBSTRING_INDEX(i.ibss,'-',1)+0 AS ISLE
     , SUBSTRING_INDEX(SUBSTRING_INDEX(i.ibss,'-',2),'-',-1)+0 AS BAY
     , SUBSTRING_INDEX(SUBSTRING_INDEX(i.ibss,'-',3),'-',-1) AS SHELF
     , SUBSTRING_INDEX(i.ibss,'-',-1)+0 AS `SLOT/BIN`
     , (SUBSTRING_INDEX(i.ibss,'-',1)+0) MOD 2 AS odd_or_even_isle
     , IF((SUBSTRING_INDEX(i.ibss,'-',1)+0) MOD 2
         ,SUBSTRING_INDEX(SUBSTRING_INDEX(i.ibss,'-',2),'-',-1)+0,NULL
       ) AS odd_bay
     , IF((SUBSTRING_INDEX(i.ibss,'-',1)+0) MOD 2
         ,NULL,SUBSTRING_INDEX(SUBSTRING_INDEX(i.ibss,'-',2),'-',-1)+0
       ) AS even_bay
  FROM ibss i
 ORDER BY -- ascending by ISLE
         SUBSTRING_INDEX(i.ibss,'-',1)+0 ASC
         -- ascending by BAY if ISLE is odd
       , IF((SUBSTRING_INDEX(i.ibss,'-',1)+0) MOD 2
           ,SUBSTRING_INDEX(SUBSTRING_INDEX(i.ibss,'-',2),'-',-1)+0,NULL
         ) ASC
         -- descending by BAY if ISLE is even
       , IF((SUBSTRING_INDEX(i.ibss,'-',1)+0) MOD 2
           ,NULL,SUBSTRING_INDEX(SUBSTRING_INDEX(i.ibss,'-',2),'-',-1)+0
         ) DESC
         -- ascending by shelf
       , SUBSTRING_INDEX(SUBSTRING_INDEX(i.ibss,'-',3),'-',-1)
         -- ascending by SLOT/BIN
       , SUBSTRING_INDEX(i.ibss,'-',-1)+0

同样,BAY 的升序/降序排序将取决于 ISLE 是偶数还是奇数,而不取决于这是否是交替过道。 (如果您希望拣货员沿着过道沿相同方向而不是相反方向移动,这种行为可能是可取的。)要根据“过道变化”来改变订单,那么我们需要添加一些额外的逻辑。

    ibss         ISLE     BAY  SHELF   SLOT/BIN  odd_or_even_isle  odd_bay  even_bay  
    ---------  ------  ------  ------  --------  ---------------- -------  ----------
    1-0-A-01        1       0  A              1                1        0      (NULL)
    1-1-D-06        1       1  D              6                1        1      (NULL)
    1-2-E-10        1       2  E             10                1        2      (NULL)
    1-2-E-11        1       2  E             11                1        2      (NULL)
    1-10-A-01       1      10  A              1                1       10      (NULL)
    2-5-F-01        2       5  F              1                0   (NULL)           5
    2-1-C-12        2       1  C             12                0   (NULL)           1
    2-1-D-02        2       1  D              2                0   (NULL)           1
    3-5-A-12        3       5  A             12                1        5      (NULL)
    3-6-D-01        3       6  D              1                1        6      (NULL)
    4-5-A-02        4       5  A              2                0   (NULL)           5
    4-5-A-03        4       5  A              3                0   (NULL)           5
    4-5-B-10        4       5  B             10                0   (NULL)           5

【讨论】:

  • 完美运行。我们肯定需要将这些位置拆分为我们数据库中的单独列,但在那之前这似乎是有效的。谢谢!
【解决方案2】:

首先,您应该正确地将这些数据元素拆分到表格中它们自己的列中。这样做之后,这个问题就变得微不足道了,甚至可以让您按架子/bin 排序:

SELECT isle,
    (IF(MOD(isle/2)=1,1,-1) * bay) AS baysort,
    bay,
    shelf,
    bin
FROM table
ORDER BY
    isle ASC,
    baysort ASC,
    shelf ASC,
    bin ASC

请注意,我正在计算 baysort 列,这基本上使 bay 成为偶数小岛的负值。

您显然可以在您的应用程序中丢弃baysort 值(或者简单地将其移至排序条件而不是选择 - 我在这里使用了选择,以便您可以直观地看到正在发生的事情)。

【讨论】:

  • 你在这里提出了一个很好的观点。我们绝对需要将这些数据标准化。这将使未来的事情变得容易得多。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-12
  • 2017-10-27
  • 1970-01-01
  • 1970-01-01
  • 2014-07-11
  • 1970-01-01
相关资源
最近更新 更多