ORDER BY更改了具有相同名称的列

时间:2015-10-03 19:05:14

标签: sql postgresql replace pattern-matching sql-order-by

我有一个表artist,其中包含多个列,例如nametype ...
我希望按字母顺序返回和排序列name,但应调整列名称。如果艺术家的名称以' (不区分大小写)开头,则应将其删除并以大写形式放在名称后面,例如'甲壳虫乐队' - > ' Beatles,THE'

这是我的代码(它没有用):

SELECT name,
  CASE
    WHEN UPPER(name) LIKE 'THE %' THEN CONCAT(RIGHT(name, length(name)-4),', THE')
  END AS name 
FROM artist
ORDER BY name

问题1:name未被替换,它会创建一个新列。

问题2:新列具有相同的名称=>列nameorder by name中不明确。

如何轻松解决这些问题?

3 个答案:

答案 0 :(得分:1)

ELSE中使用CASE子句:

SELECT
  CASE
    WHEN UPPER(name) LIKE 'THE %' THEN CONCAT(RIGHT(name, length(name)-4),', THE')
    ELSE name
  END AS name 
FROM artist
ORDER BY name

答案 1 :(得分:0)

如果您只想要这个用于排序,那么您只能将逻辑放在order by子句中:

order by (case when name ilike 'the%'
               then substring(name from 5) || ', The'
               else name
          end)

如果您还想在select子句中使用此列,请使用name以外的别名。这已经用于您的第一栏:

select name,
       (case when name ilike 'the%'
             then substring(name from 5) || ', The'
             else name
        end) as munged_name
. . .
order by munged_name

注意:ilike是不区分大小写的like的Postgres扩展。

答案 2 :(得分:0)

查询

SELECT CASE WHEN name ILIKE 'THE %'  -- simpler
            THEN right(name, -4) || ', THE'  -- simpler, faster
            ELSE name END AS name  -- but better use a distinct alias
      , *
FROM   artist
ORDER  BY 1;  -- positional reference to 1st output column

原理

查询中的表达式必须与使用此索引相同。

正确的测试用例

CREATE INDEX artist_name_sort_idx ON artist 
 ((CASE WHEN name ILIKE 'THE %' THEN right(name, -4) || ', THE' ELSE name END));

结果:

WITH artist(artist_id, name) AS (
   VALUES
      (1, 'The Beatles')   
    , (2, 'tHe bEatles')
    , (3, 'The The')
    , (4, 'Then')
    , (5, 'The X')
    , (6, 'Theodor')
    , (7, 'Abba')
    , (8, 'ZZ TOP')
    , (9, 'The ')  -- unlikely corner case, I don't think it would pay to test for it
    , (10, '')      -- empty string
    , (11, NULL)   -- NULL
   )
SELECT CASE WHEN name ILIKE 'THE %' THEN right(name, -4) || ', THE' ELSE name END AS name
      , *
FROM   artist
ORDER  BY 1;