2010-09-12 5 views
11

Sto usando C# per visualizzare un elenco di titoli di film che sto chiamando da un database SQLite. Attualmente, sto usando una classe ListBox personalizzata che ha una funzione per ordinare il testo che rimuove la parola "The" dall'inizio di ogni elemento. Tuttavia, non sembra esattamente il modo più semplice per farlo, dal momento che chiama dal database SQLite e dagli ordinamenti quindi da. Preferirei ridurlo a un solo passaggio, si spera che venga estratto direttamente dal database nella mia query "SELECT".Come posso ordinare una query SQLite ignorando gli articoli ("il", "un", ecc.)?

Ho fatto qualche ricerca su questo, e ho trovato alcuni suggerimenti, tra cui la creazione di una colonna di ordinamento extra nel database. Mentre questa è certamente una possibilità, mi chiedo se ci siano opzioni più semplici che non richiedono l'inserimento di informazioni duplicate quasi identiche (specialmente se il database diventa più grande). Sono abbastanza nuovo per SQLite, ma ho letto qualcosa sulla creazione di una funzione di fascicolazione che può essere utilizzata per creare ordini personalizzati. Tuttavia, non sono sicuro che sia appropriato utilizzarlo e non riesco a trovare alcun aiuto nell'implementarlo in C#.

Speravo che qualcuno potesse essere in grado di condividere alcune indicazioni. Se una colonna di ordinamento in più è il modo migliore per andare, allora è quello che farò.

risposta

6

Per evitare di inserire dati duplicati, che dire di avere due colonne: TITLE_PREFIX (in genere vuoto, ma a volte contiene "The" o "A", nessun indice su questa colonna) e TITLE (contiene il titolo senza "The" o "A": questa è la colonna su cui si crea l'indice). Per visualizzare i dati, è necessario combinare TITLE_PREFIX e TITLE. Ma tu cerca solo su TITLE.

1

È possibile memorizzare ciascun titolo in 2 parti: title e prefix.

Con SQLite è possibile combinare 2 valori di stringa tramite || operator noto anche come concatenate operator.

Ecco un esempio:

SELECT prefix || ' ' || title FROM movies ORDER BY title 

È inoltre possibile utilizzare ltrim nel caso in cui prefisso è vuota, quindi non si dispone di uno spazio nella parte anteriore:

SELECT ltrim(prefix || ' ' || title) FROM movies ORDER BY title 

Un'altra alternativa è quello di memorizzare il prefisso alla fine del titolo. Per esempio, a un sacco di negozi di film si vedrà qualcosa di simile:

tre moschettieri, Il

0

In C# Codice

Se si voleva fare questo all'interno di C#, utilizzare LINQ per fare l'ordine per te. Ho pubblicato un full sample on PasteBin.Questo vi permetterà di:

  • evitare la duplicazione dei dati nel database
  • sfruttare gli indici DB come si farebbe normalmente, non importa quale RDBMS
  • mettere in parole non significative in un file di configurazione, riducendo in tal modo i tempi di inattività/ricostruzione/ridistribuire quando si modifica la lista
  • garantire una soluzione è più leggibile nel codice client
DropDownList1.DataSource = myBooks.OrderBy(n => ReplaceNoise(n.Title)) 

public string ReplaceNoise(string input) 
{ 
    string[] noise = new string[] { "the", "an", "a" }; 

    //surely this could be LINQ'd 
    foreach (string n in noise) 
    { 
     if (input.ToLower().StartsWith(n)) 
     { 
      return input.Substring(n.Length).Trim(); 
     } 
    } 
    return input; 
} 

Entro la vostra dichiarazione di SQLite

Che ne dite di semplicemente sostituendo le parole non significative con spazi vuoti nell'ordine da? È un brutto primo passo, ma considera seriamente una nuova colonna per memorizzare questo valore ai fini dell'ordinamento.

ORDER BY REPLACE(REPLACE([title],'the',''), 'a', '') 

Certo, questo diventa brutto quando si finisce con questo:

REPLACE(REPLACE(REPLACE(REPLACE([title],'The ',''),'a',''),'of',''),'by','') 
+2

che non permetterà il database da utilizzare un indice su 'title' se ne esiste uno. E sembra che l'OP si aspetti molti dati. –

+0

@Daniel: in effetti, hai ragione sull'indice. Per i migliori risultati, OP potrebbe voler trovare un altro DB diverso da SQLite. La soluzione C# è molto più attraente. L'ordinamento appartiene davvero al client, indipendentemente dal RDBMS. –

+0

@downvoter: ti interessa spiegare perché l'ordinamento tramite LINQ non aiuta? Che ne dici del suggerimento di una nuova colonna per memorizzare il valore di "ordinamento"? In che modo uno di questi suggerimenti ottiene un downvote? –

0

Si potrebbe provare a costruire un tavolo che supporta la ricerca full-text (utilizzando il modulo FTS) sul titolo. Quindi sarai in grado di fare ricerche veloci su qualsiasi parola del titolo senza richiedere molto lavoro extra da parte tua. Ad esempio, una query utente di good brutto brutto potrebbe produrre "Il buono, il brutto e il cattivo" come uno dei suoi primi risultati. Il costo aggiuntivo di tutto questo è circa un quarto della lunghezza del testo stesso in generale, ma potrebbe essere più per il set di dati, in quanto i titoli non sono completamente in inglese. Devi anche dedicare del tempo a costruire quegli indici extra - non vuoi costruirli sul tuo set di dati principale su un sistema live (ovviamente) - ma non dovrebbe essere un problema troppo grande.

0

Creare una colonna virtuale (risultato di una funzione che può essere implementata in C#) e ordinare su questa colonna virtuale. La funzione potrebbe spostare "The" alla fine come in "Three Musketeers, The" o scartare "The", qualunque cosa tu voglia che faccia.

+0

C'è una documentazione su come farlo da qualche parte sul sito System.Data.SQLite. I tipi sarebbero fatti nella tua istruzione SELECT in SQLite, anche se avresti rinunciato all'accesso all'indice sull'ordinamento. Presumo che tu non abbia migliaia e migliaia di titoli nel tuo set di risultati se li stai mettendo in una Listbox adesso, quindi non dovrebbe esserci alcun problema. – Tim

+0

Ecco un esempio di cosa intendo: – Tim

+0

http://www.ivankristianto.com/software-development/visual-studio-net/howto-make-user-defined-function-in-sqlite-ado-net-with- csharp/957 / – Tim

4

ecco la soluzione:

ORDER BY (CASE 
    WHEN sortTitle LIKE 'the %' THEN substr(sortTitle,5) 
    WHEN sortTitle LIKE 'a %' THEN substr(sortTitle,3) 
    WHEN sortTitle LIKE 'an %' THEN substr(sortTitle,4) 
    ELSE sortTitle END) 
Problemi correlati