2009-05-07 19 views
19

Vorrei produrre un elenco di caratteri di tutte le prime lettere di colonna nel mio database. L'SQL sotto illistrats quello che mi piacerebbe tornare.Restituzione del primo carattere DISTINCT di un campo (MySQL)

 
SELECT DISTINCT first_character(name) FROM mydatabase 

C'è un modo per farlo in MySQL?

EDIT Qual è il vantaggio di utilizzare SUBSTRING sopra LEFT e viceversa?

EDIT Attualmente ci sono circa 1700 record nella tabella e in crescita.

+1

Quanti dischi hai nel tuo tavolo?Volevo pubblicare una versione ottimizzata ma non so se disturbare :) – Quassnoi

+0

OK, l'ho postato comunque :) Probabilmente domani farò un post nel mio blog fuori dalla tua domanda. – Quassnoi

risposta

55

Siamo spiacenti per fare questo, ma ho capito esattamente quello che mi serviva per fare proprio ora.

 
SELECT DISTINCT LEFT(name, 1) FROM mydatabase 

Questo ha restituito un elenco dei primi, distinti, singoli caratteri con cui è iniziata ogni riga della colonna. Ho aggiunto cambiato in seguito per ottenerlo l'elenco in ordine alfanumerico:

 
SELECT DISTINCT LEFT(name, 1) as letter FROM mydatabase ORDER BY letter 

funziona come un fascino.

+0

È perfettamente accettabile pubblicare le risposte alle proprie domande. +1 –

+0

Io uso 'SUBSTRING()' perché è uno standard SQL. Non ho trovato uno standard per la funzione 'LEFT()'. http://troels.arvin.dk/db/rdbms/#functions-SUBSTRING – Sonny

9

sembra semplice:

select distinct substring(field,1,1) as char 
from mytable 
+1

Utilizzo standard SQL: 'SUBSTRING (input FROM start-position [FOR length])' -> 'SUBSTRING (campo FROM 1 FOR 1)' – Sonny

+0

@Sonny: sintassi errata vicino alla parola chiave 'FROM'. – Andomar

+0

Non sono sicuro del perché dici "Sintassi errata" la sintassi che ho postato è mostrata qui: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_substring - La query completa dovrebbe essere questo: 'SELECT DISTINCT SUBSTRING (campo FROM 1 FOR 1) AS char FROM mytable' – Sonny

9

Per la tabella corrente di 1,700 righe la soluzione è OK.

Se si dispone dello 100,000 di righe, lo DISTINCT potrebbe diventare inefficiente.

Ecco l'articolo nel mio blog che mostra come farlo in modo efficiente:

Questa soluzione impiega un indice su name. Salterà sopra i tasti indice, selezionando ogni prima lettera al massimo una volta.

In primo luogo, è necessario creare una funzione:

CREATE FUNCTION fn_get_next_code(initial INT) RETURNS INT 
NOT DETERMINISTIC 
READS SQL DATA 
BEGIN 
     DECLARE _next VARCHAR(200); 
     DECLARE EXIT HANDLER FOR NOT FOUND RETURN NULL; 
     SELECT ORD(SUBSTRING(name, 1, 1)) 
     INTO _next 
     FROM t_names 
     WHERE name >= CHAR(initial + 1) 
     ORDER BY 
       name 
     LIMIT 1; 
     RETURN _next; 
END 

Questa funzione, dato un codice di una lettera di partenza, restituisce la prima lettera di partenza vicino alla data dal vostro tavolo.

secondo luogo, utilizzare questa funzione in una query:

SELECT CHAR(@r) AS starting, 
     @r := fn_get_next_letter(@r) AS next 
FROM (
     SELECT @r := ORD(LEFT(MIN(name), 1)) 
     ) vars, mytable 
WHERE @r IS NOT NULL 

In ogni iterazione, sessione variabile @r salterà la lettera successiva partenza utilizzando un indice.

Questo sarà molto veloce, ma si ripaga da solo se si dispone di centinaia di migliaia di righe.

Altrimenti basta usare DISTINCT.

+0

+1, contrassegnato con un segnalibro per quando devo interrogare la tabella delle Nazioni Unite di tutte le entità denominate nell'universo: D – Andomar

+0

Assicurarsi che sia in US ASCII, non ha provato su Unicode :) – Quassnoi

Problemi correlati