SQL:ORDER BY使用特定列中的子字符串...可能吗?

时间:2011-11-18 19:14:47

标签: sql sorting substring

我有一个数据库,其列为npID,标题,网址和问题。

以下是两年参赛作品的示例:

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

7 个答案:

答案 0 :(得分:10)

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

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等)对它们进行排序。

答案 1 :(得分:7)

标准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;
PostgreSQL 9.1添加了

left() and right()right()的诀窍是使用负数从左边修剪一定数量的字符。

语法变体

这些是等效的(对于< = 100个字符的字符串):

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

答案 2 :(得分:1)

这是同一主题的变体

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

是的,你可以在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 :(得分:0)

尝试这种方法(这是在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

答案 6 :(得分:0)

SELECT Column1, row_number() over(order by substring(column2,280,9)) 
FROM YourTable 

这将给出子串column2的order by