How to sort in SQL, ignoring articles ('the“, ”a', “an” etc)

[亡魂溺海] 提交于 2019-12-05 03:24:45

One approach I've seen was to have two columns - one for display and the other for sorting:

description  |  sort_desc
----------------------------
The the      | the, The
A test         | test, A
I, Robot      | i, Robot

I haven't done any real world testing, but this has the benefit of being able to use an index and doesn't require string manipulation every time you want to order by the description. Unless your database supports materialized views (which MySQL doesn't), implementing the logic as a computed column in a view wouldn't provide any benefit because you can't index the computed column.

I've been using this for years, but can't remember where I found it:

SELECT 
CASE
    WHEN SUBSTRING_INDEX(Title, ' ', 1) IN ('a', 'an', 'the') 
    THEN CONCAT( SUBSTRING( Title, INSTR(Title, ' ') + 1 ), ', ', SUBSTRING_INDEX(Title, ' ', 1) ) 
    ELSE Title 
    END AS TitleSort,
Title AS OriginalTitle 
FROM yourtable 
ORDER BY TitleSort 

Yielding:

TitleSort                  | OriginalTitle
------------------------------------------------------
All About Everything       | All About Everything
Beginning Of The End, The  | The Beginning Of The End
Interesting Story, An      | An Interesting Story
Very Long Story, A         | A Very Long Story

I can only speak for SQL Server: you use LTRIM within CASE statements. No LOWER function is needed because selections are not case sensitive by default. However, if you want to ignore articles then I would suggest you use a noise word dictionary and set up a full text indexing catalog. I am unsure if other implementations are SQL support this.

For Postgres specifically, you can use regexp_replace to do the work for you:

BEGIN;
CREATE TEMPORARY TABLE book (name VARCHAR NOT NULL) ON COMMIT DROP;
INSERT INTO book (name) VALUES ('The Hitchhiker’s Guide to the Galaxy');
INSERT INTO book (name) VALUES ('The Restaurant at the End of the Universe');
INSERT INTO book (name) VALUES ('Life, the Universe and Everything');
INSERT INTO book (name) VALUES ('So Long, and Thanks for All the Fish');
INSERT INTO book (name) VALUES ('Mostly Harmless');
INSERT INTO book (name) VALUES ('A book by Douglas Adams');
INSERT INTO book (name) VALUES ('Another book by Douglas Adams');
INSERT INTO book (name) VALUES ('An omnibus of books by Douglas Adams');

SELECT name FROM book ORDER BY name;
SELECT name, regexp_replace(lower(name), '^(an?|the) (.*)$', '\2, \1') FROM book ORDER BY 2;
SELECT name FROM book ORDER BY regexp_replace(lower(name), '^(an?|the) (.*)$', '\2, \1');
COMMIT;
JBC

LOWER is needed. While SELECT is not case-sensitive, ORDER BY is.

Try the following:

ORDER BY replace(replace(replace(YOURCOLUMN,'THE',''),'a\'',''),'an','')

Not tested!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!