按自定义顺序排序多个字段,空字段最后

时间:2017-10-04 05:51:36

标签: php mysql sorting

我正在编辑这个问题,因为原文的措辞很差,并且有错误的信息,直到它被回答后我才看到,这可以理解地造成了混乱。由于我无法删除它,我会尽力编辑它。

我在一个大表中有3个字段,用于存储与时间轴有关的信息,我想对所有这些字段应用自定义排序。

日期”列包含年份或时代名称。在此示例中,时代名称有3个选项:早期时间中期时间晚期时间。如果“日期”列中存在一年,则在同一行中,“时代”和/或“ Era2 ”列可以选择具有时代名称。如果“ Era ”列中没有值,则“ Era2 ”列中永远不会有值。

我想执行以下操作:

  • 我想在最底部将所有三列的行都清空。

  • 然后,我想要的所有“日期”列 年份 - 该行中的“ Era ”和“ Era2 ”列为空 - 朝向底部。年份可按升序排序。

  • 然后,我想订购任何带有时代名称的列 (“日期”,“时代”或“ Era2 ”列)预定义 自定义订单(见下文)。在“日期”中定义年份的行和“时代”或“ Era2 ”列中的值将在“日期“仅包含时代名称的列。

预定义订单示例:

 ("Early Era","Mid Era","Late Era")

当前未排序的表格:

Date           | Era           | Era2
-------------- |-------------- |-------------- 
         1991  | Early Era     |
         1992  | Early Era     |
    Early Era  |               |
         1999  | Mid Era       | Late Era
         1999  | Mid Era       | Early Era
      Mid Era  |               |  
     Late Era  |               |  
    Early Era  |               |  
               | Mid Era       |  
               | Late Era      |        
         2009  |               |    
     Late Era  |               |            
         2014  | Late Era      |
               |               |              
         2015  |               |         
         1992  |               |            
         1999  |               |            
         1992  | Early Era     |             

排序后的所需结果:

Date           | Era           | Era2
-------------- |-------------- |-------------- 
         1991  | Early Era     |
         1992  | Early Era     |
         1992  | Early Era     |       
    Early Era  |               |        
    Early Era  |               |
         1999  | Mid Era       | Early Era
         1999  | Mid Era       | Late Era
      Mid Era  |               |  
               | Mid Era       |  
         2014  | Late Era      |
     Late Era  |               |
     Late Era  |               |    
               | Late Era      |  
         1992  |               |  
         1999  |               |                     
         2009  |               |              
         2015  |               |         
               |               |                    

目前的代码并不完全有效,但主要是在那里:

SELECT *
FROM yourTable
ORDER BY
        CASE WHEN Date LIKE '%Era%' OR Era LIKE '%Era%' THEN 0 ELSE 1 END,
        CASE WHEN Date != '' THEN 0 ELSE 1 END,
        FIELD(CASE WHEN Era = '' THEN Date ELSE Era END, 'Late Era','Mid Era','Early Era') DESC, 
        CASE WHEN Era LIKE '%Era%'  THEN 0
             WHEN Date LIKE '%Era%' THEN 1 END;

不需要的订单与当前代码,排序后

Date           | Era           | Era2
-------------- |-------------- |-------------- 
         1991  | Early Era     |
         1992  | Early Era     |
         1992  | Early Era     |       
    Early Era  |               |        
    Early Era  |               |
         1999  | Mid Era       | Late Era
         1999  | Mid Era       | Early Era
      Mid Era  |               |  
         2014  | Late Era      |
     Late Era  |               |  
     Late Era  |               |  
               | Mid Era       |  
               | Late Era      |        
         2009  |               |              
         2015  |               |         
         1992  |               |            
         1999  |               |           
               |               |              

实例:http://rextester.com/CAMA42792

请注意,“ Era2 ”列中的时代名称未正确排序。此外,“时代”列中的时代名称(具有空“日期”列的列)仍未正确排序 - 它们应与时代名称分组。第三,最底层的年份处于正确的位置,它们不是按升序排列的。希望这是有道理的,如果有任何需要进一步解释的话,请告诉我,我理解这有点令人费解。提前感谢您的帮助。

编辑 - 这是一个与原始版本截然不同的问题,但希望它澄清并纠正我的初始版本中存在的问题。如果mod认为最好,他们可能会删除这个问题,我很乐意创建一个新问题。

2 个答案:

答案 0 :(得分:2)

回答这个问题的人最初给了我一个部分工作的答案,在上面的评论中鼓励我在完成解决方案后编辑他的答案。一旦我获得了完整的工作解决方案,我就编辑了他的答案,但是这些编辑没有得到批准。所以我想为任何发现它有用的人发布完整的工作解决方案:

SELECT *
FROM yourTable
ORDER BY
      CASE WHEN concat(Era,Era,Date) LIKE '%Era%' THEN 0 else 1 end,
      FIELD(CASE WHEN Era = '' THEN Date ELSE Era END, 'Late Era','Mid Era','Early Era') desc,
      CASE WHEN Date!='' THEN 0 ELSE 1 end,
      CASE WHEN date not like '%Era%' THEN 0 else 1 end,
      date, Era2

SQLFiddle

答案 1 :(得分:1)

您可以尝试以下查询:

SELECT *
FROM yourTable
ORDER BY
    CASE WHEN Date LIKE '%Era%' OR Era LIKE '%Era%' THEN 0 ELSE 1 END,
    CASE WHEN Date IS NOT NULL THEN 0 ELSE 1 END,
    FIELD(COALESCE(Era, Date), 'Late Era','Mid Era','Early Era') DESC, 
    CASE WHEN Era LIKE '%Era%'  THEN 0
         WHEN Date LIKE '%Era%' THEN 1 END;

此查询基于我在预期输出中看到的内容。也就是说,它按优先顺序选择以下内容:

  • 记录DateEra在没有此文字的记录之前显示文字Era的记录
  • 日期为NULL的记录来自日期不是NULL
  • 的日期
  • 然后按早,中,晚,NULL排序(你几乎已经有了这个)
  • 最终将Date时代的记录放在Era
  • 之后的记录中

在这里演示:

Rextester