2010-07-15 8 views
8

Questo risulta molto, e posso vedere che è venuto su StackOverflow per XSLT, Ruby e Drupal ma io non so Lo vedo specificamente per SQL.Come ordinare in SQL, ignorando gli articoli ("il", "un", "un" ecc.)

Quindi la domanda è: come si ordinano i titoli correttamente quando iniziano con "The", "A" o "An"?

Un modo è semplicemente quello di TRIM() quelle stringhe:

ORDER BY TRIM( 
    LEADING 'a ' FROM 
    TRIM( 
    LEADING 'an ' FROM 
    TRIM( 
     LEADING 'the ' FROM LOWER(title) 
    ) 
    ) 
) 

che era suggested on AskMeFi un po 'indietro (Ha bisogno che LOWER() funzione?).

So che ho anche visto una sorta di implementazione Case/Switch di questo, ma è un po 'difficile per Google.

Ovviamente ci sono un certo numero di possibili soluzioni. Ciò che sarebbe positivo sono i guru SQL che hanno un impatto sul rendimento.

+0

D'accordo con un commentatore su una delle domande SO collegate: le regole possono risultare più complicate di quanto sembri. Il tuo suggerimento particolare, ad esempio, probabilmente non riuscirebbe a ordinare correttamente il seguente elenco: "The A Test", "The B Test", "The C Test". –

risposta

6

Un approccio che ho visto era di avere due colonne - uno per la visualizzazione e l'altro per l'ordinamento:

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

Non ho fatto alcun test del mondo reale, ma questo ha il vantaggio di essere in grado utilizzare un indice e non richiede la manipolazione delle stringhe ogni volta che si desidera ordinare dalla descrizione. A meno che il tuo database non supporti le viste materializzate (che MySQL non lo fa), implementare la logica come una colonna calcolata in una vista non fornirebbe alcun beneficio perché non puoi indicizzare la colonna calcolata.

0

Posso parlare solo per SQL Server: si utilizza LTRIM all'interno delle istruzioni CASE. Non è necessaria alcuna funzione INFERIORE perché le selezioni non sono sensibili alla distinzione tra maiuscole e minuscole. Tuttavia, se si desidera ignorare gli articoli, suggerirei di utilizzare un dizionario di parole non significative e di impostare un catalogo di indicizzazione di testo completo. Non sono sicuro che altre implementazioni supportino SQL questo.

+0

La distinzione tra maiuscole e minuscole dipende dalla fascicolazione. Full Text Search (FTS) è disponibile su MySQL, Oracle, SQL Server ... Non so cosa sia PostgreSQL ma sono sicuro che abbia funzionalità native. E ci sono FTS di terze parti come la sfinge ... –

+0

"si usa LTRIM all'interno delle istruzioni CASE" - significa che si fa l'equivalente di "se inizia con" il ", taglia"? Mi chiedevo se questo avrebbe rallentato il processo, al contrario di un blank TRIM() che potrebbe fallire il più delle volte. – AmbroseChapel

+0

LTRIM elimina gli spazi iniziali – CarneyCode

-1

LOWER necessario. Mentre SELECT non fa distinzione tra maiuscole e minuscole, è ORDER BY.

-3

Provare quanto segue:

ORDER BY replace (sostituzione (sostituzione (YOURCOLUMN, 'THE', ''), 'un \'', ''), 'una', '')

Non testato!

+1

Sorpreso nessuno ha spiegato il problema con questo. Quando si ordina, si desidera sostituire gli articoli LEADING, mentre questo sostituirà TUTTI gli articoli. –

2

Sto usando questo per anni, ma non ricordo dove l'ho trovato:

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 

Cedendo:

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 
0

Per Postgres specifico, è possibile utilizzare per fare il REGEXP_REPLACE lavoro per voi:

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; 
Problemi correlati