【问题标题】:SQL: ORDER BY using a substring within a specific column... possible?SQL: ORDER BY 在特定列中使用子字符串...可能吗?
【发布时间】:2012-01-01 12:52:11
【问题描述】:

我有一个数据库,其列是 npID、标题、URL 和问题。

以下是两年条目的示例:

npID               title               URL               issue
88                 EMR Newsletter      a.com             2010 Third_Quarter
89                 EMR Newsletter      b.com             2010 Second_Quarter
43                 EMR Newsletter      c.com             2010 First_Quarter
47                 EMR Newsletter      d.com             2009 Winter
45                 EMR Newsletter      e.com             2009 Summer
46                 EMR Newsletter      f.com             2009 Spring
44                 EMR Newsletter      g.com             2009 Fall

我想做的是能够根据“问题”列中的子字符串对结果进行排序。然而,直到 2010 年,客户才使用季节作为标题,并且在 2010 年,他们开始使用季度。在“ORDER BY”中是否有一种方法可以提供一个单词列表,以便在“问题”值中的任何位置找到它们时/何时对其进行排序?

我希望最终结果是这样的:

npID               title               URL               issue
43                 EMR Newsletter      c.com             2010 First_Quarter
89                 EMR Newsletter      b.com             2010 Second_Quarter
88                 EMR Newsletter      a.com             2010 Third_Quarter
47                 EMR Newsletter      d.com             2009 Winter
45                 EMR Newsletter      e.com             2009 Summer
46                 EMR Newsletter      f.com             2009 Spring
44                 EMR Newsletter      g.com             2009 Fall

【问题讨论】:

  • 我不明白您想将 2009 年的条目排序为 Winter->Summer->Spring->Fall。那是怎么回事?
  • 这是客户想要的...我不问问题
  • Gotchya.. 以为是错字什么的。
  • 示例中的排序顺序搞砸了。

标签: sql sorting substring


【解决方案1】:

您可以在ORDER BY 中添加CASE 语句来完成此操作。更好的方法是更改​​应用程序和表,以便在您有开发时间时将这些相关数据实际存储在它所属的列中。

ORDER BY
    CAST(SUBSTRING(issue, 1, 4) AS INT) DESC,  -- Year
    CASE
        WHEN issue LIKE '%First_Quarter' OR issue LIKE '%Winter' THEN 1
        WHEN issue LIKE '%Second_Quarter' OR issue LIKE '%Spring' THEN 2
        WHEN issue LIKE '%Third_Quarter' OR issue LIKE '%Summer' THEN 3
        WHEN issue LIKE '%Fourth_Quarter' OR issue LIKE '%Fall' THEN 4
    END

随心所欲地订购季节。您还可以通过调整CASE 语句以特定方式(Q1 后接 Spring,Q2 后接等)对它们进行排序。

【讨论】:

  • 有效 - 但我在 2010 .... 问题之前得到了 2009 .... 的东西.....
  • 应该是substring(issue,1,4) desc),
  • 感谢指正。我已经适当地改变了答案
【解决方案2】:

标准 SQL

ORDER BY 中尝试CASE 语句:

SELECT npID, title, URL, issue
FROM   tbl
ORDER  BY substring(issue, 1, 4) DESC
     , CASE 
          WHEN substring(issue, 6, 100) IN ('Winter','First_Quarter')  THEN 1
          WHEN substring(issue, 6, 100) IN ('Summer','Second_Quarter') THEN 2
          WHEN substring(issue, 6, 100) IN ('Spring','Third_Quarter')  THEN 3
          WHEN substring(issue, 6, 100) IN ('Fall',  'Fourth Quarter') THEN 4
          ELSE 5 
       END;

Winter -> Summer -> Spring - 这是客户想要的! :)

优化性能

一个“简单的”CASE 应该表现更好,因为表达式只计算一次。
right(issue, -5) 等价于substring(issue, 6, 100),但要快一点:

SELECT npid, title, url, issue
FROM   tbl
ORDER  BY left(issue, 4) DESC
     , CASE right(issue, -5)
          WHEN 'Winter'         THEN 1
          WHEN 'First_Quarter'  THEN 1
          WHEN 'Summer'         THEN 2
          WHEN 'Second_Quarter' THEN 2
          WHEN 'Spring'         THEN 3
          WHEN 'Third_Quarter'  THEN 3
          WHEN 'Fall'           THEN 4
          WHEN 'Fourth Quarter' THEN 4
          ELSE 5 
       END;

left() and right() 已添加到 PostgreSQL 9.1。 right() 的诀窍是使用负数从左边修剪恒定数量的字符。

语法变体

这是等效的(对于

SELECT substring(issue from 6 for 100) AS substring1
     , substring(issue, 6, 100)        AS substring2
     , substring(issue, 6)             AS substring3
     , substr(issue, 6, 100)           AS substr1
     , substr(issue, 6)                AS substr2
     , right(issue, -5)                AS right0
FROM   tbl;

-> sqlfiddle

【讨论】:

  • 收到错误:Msg 174, Level 15, State 1, Line 15 - The substring function requires 3 argument(s).
  • @marc_s:在某些实现中,substring() 的第三个参数是可选的(就像在 PostgreSQL 中一样)。我给你加了一个。也更改为标准 SQL 语法变体from x for y
  • 抱歉,是的 - 我在 SQL Server 2008 R2 上进行测试,需要第三个参数。
  • 对于“从 1 到 4 的问题”部分,我收到“关键字 'from' 附近的语法不正确”:(
  • @Brds:好的,现在您使用的是哪个 DBMS?猜测就够了。
【解决方案3】:

这是同一主题的变体

ORDER BY
    SUBSTRING(issue,1,4) Desc,

CASE SUBSTRING(issue,6, LEN(issue) - 5)
   WHEN 'First_Quarter' THEN 1
   WHEN 'Second_Quarter' THEN 2
   WHEN 'Second_Quarter' THEN 3
   WHEN 'Winter' then 1
   WHEN 'Spring' then 2
   WHEN 'Summer' then 3
   WHEN 'Fall' then 4
END

【讨论】:

    【解决方案4】:

    是的,您可以在 sql 命令中的任何位置使用 if/then 结构。

    您是否已有适合您的子字符串模式?如果是这样,你可以使用类似的东西:

    ORDER BY (IF (SUBSTRING(first_match_of_issue) IS NOT NULL) THEN first_match_of_issue ELSE second_match_of_issue))
    

    但是 - 如果您已经知道它们将是什么,那么其他答案中提到的 CASE 语句可能更容易。

    【讨论】:

      【解决方案5】:

      试试这个方法(这是在 T-SQL 中):

      select
              *
          from
              your_table as t
          order by
              substring([issue], 1, 4) desc,
              case substring([issue], 6, len([issue]) - 5)
                  when 'First_Quarter' then 1
                  when 'Second_Quarter' then 2
                  when 'Third_Quarter' then 3
                  when 'Fourth_quarter' then 4
                  when 'Spring' then 3
                  when 'Summer' then 2
                  when 'Fall' then 4
                  when 'Winter' then 1
                  else 5 -- show unexpected input last
              end asc
      

      【讨论】:

      • 要使其真正工作,它应该是CAST(SUBSTRING(issue, 1, 4) AS INT) DESC,以便它以数字降序排列... . (否则它仍然会被排序为 strings 这不一定与数字排序的排序顺序相同)
      • @marc_s:当然,尽管您说得非常正确,但我认为总体上描述该方法比细致入微的复制和粘贴解决方案更有价值。而且,在现实世界中,我不知道四位数字字符串的排序方式与等效整数不同的情况。我们不太可能看到任何 3 位数或 5 位数的年份出现。
      【解决方案6】:

      您可以将子字符串作为被选择数据的一部分

      SELECT npId, title, URL, issue, SUBSTRING(issue, 4) AS strsort FROM tbl ORDER BY strsort, issue
      

      【讨论】:

      • 缺少FROM .... 子句并出现错误:Msg 174, Level 15, State 1, Line 10 - The substring function requires 3 argument(s).
      • 你错过了季度和季节的子顺序
      【解决方案7】:
      SELECT Column1, row_number() over(order by substring(column2,280,9)) 
      FROM YourTable 
      

      这将给出子字符串 column2 的 order by

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-15
        • 2011-01-11
        • 2014-10-12
        • 2014-08-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多