Sql 按名称相同的已更改列排序

Sql 按名称相同的已更改列排序,sql,postgresql,replace,pattern-matching,sql-order-by,Sql,Postgresql,Replace,Pattern Matching,Sql Order By,我有一个表artist,有几个列,如name,type… 我希望返回列名称,并按字母顺序排列,但应调整列名。如果艺术家的姓名以“the”(不区分大小写)开头,则应将其删除并置于大写名称后面,例如“the Beatles”->“Beatles,the” 这是我的代码(不起作用): 问题1:name未被替换,它会创建一个新列 问题2:新列具有相同的名称=>columnname在orderbyname中不明确 如何轻松解决这些问题?在案例中使用ELSE子句: SELECT CASE WHE

我有一个表
artist
,有几个列,如
name
type

我希望返回列
名称
,并按字母顺序排列,但应调整列名。如果艺术家的姓名以“the”(不区分大小写)开头,则应将其删除并置于大写名称后面,例如“the Beatles”->“Beatles,the”

这是我的代码(不起作用):

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

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


如何轻松解决这些问题?

案例中使用
ELSE
子句

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

如果您只想将其用于排序,则可以将逻辑仅放在
order by
子句中:

order by (case when name ilike 'the%'
               then substring(name from 5) || ', The'
               else name
          end)
如果您还希望在
选择
子句中使用此列,请使用
名称
以外的别名。已用于第一列的:

select name,
       (case when name ilike 'the%'
             then substring(name from 5) || ', The'
             else name
        end) as munged_name
. . .
order by munged_name
注意:
ilike
是Postgres的扩展,用于不区分大小写的
like

查询 根本原因
  • 获取字符串减去n个前导字符的最简单、最快的表达式是:

  • ILIKE
    lower()
    /
    upper()更简单,比如…

  • 您不需要,普通连接运算符也可以更快地执行相同的操作,因为表达式
    right(name,-4)
    在此上下文中保证
    notnull

  • 当与列名的SQL可见性规则混淆时,或者当存在重复的输出列名时(这在Postgres中是完全合法的),您还可以在
    GROUP BY
    ORDER BY
    DISTINCT ON(…)
    子句中使用位置引用

    然而,首先使用重复的输出列名是不明智的,也没有什么用处的。而是使用不同的名称

  • 如果您经常运行此查询,我建议在同一表达式上使用一个查询,以获得更快的结果:

    CREATE INDEX artist_name_sort_idx ON artist 
     ((CASE WHEN name ILIKE 'THE %' THEN right(name, -4) || ', THE' ELSE name END));
    
查询中的表达式必须相同才能使用此索引

正确的测试用例 结果:

     name     | artist_id |    name
--------------+-----------+-------------
              |        10 |
 , THE        |         9 | The           -- remaining corner case
 Abba         |         7 | Abba
 bEatles, THE |         2 | tHe bEatles
 Beatles, THE |         1 | The Beatles
 The, THE     |         3 | The The
 Then         |         4 | Then
 Theodor      |         6 | Theodor
 X, THE       |         5 | The X
 ZZ TOP       |         8 | ZZ TOP
 <NULL>       |        11 | <NULL>
name |艺术家| id | name
--------------+-----------+-------------
|        10 |
| 9 | |剩余角案例
阿巴| 7 |阿巴
披头士乐队,披头士乐队
披头士乐队,披头士乐队
这个,这个| 3 |这个,
然后| 4 |然后
西奥多| 6 |西奥多
十、 |5 | X
ZZ顶部| 8 | ZZ顶部
|        11 | 

请始终添加您的Postgres版本。这并不能解决以下问题:
问题2:新列具有相同的名称=>按名称排列的列名不明确。
@ErwinBrandstetter
问题1。名称不会被替换,它将创建一个新列。
。原始名称替换为
大小写
和别名。我不明白为什么这是模棱两可的。是否可以提供SQLFIDLE with error?
ORDER BY name
如果输出中有多个名为name的列,则引发异常。@ERWINBRANDSTETER该点在我的查询中没有多个列。作者明确表示,他希望替换名称,而不是创建新列,如果他想要两列,则需要别名。
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;
     name     | artist_id |    name
--------------+-----------+-------------
              |        10 |
 , THE        |         9 | The           -- remaining corner case
 Abba         |         7 | Abba
 bEatles, THE |         2 | tHe bEatles
 Beatles, THE |         1 | The Beatles
 The, THE     |         3 | The The
 Then         |         4 | Then
 Theodor      |         6 | Theodor
 X, THE       |         5 | The X
 ZZ TOP       |         8 | ZZ TOP
 <NULL>       |        11 | <NULL>