2014-12-05 15 views
9

Utilizzo di Oracle 11gR2 Expression Edition. miei dati si presenta come segue
Oracle NOT BETWEEN per il confronto delle stringhe non dà lo stesso risultato di <= and > =

ordertype 
--------- 
ZOCO 
ZOSA 
ZOST 

Stiamo cercando di scoprire i record in cui la colonna non è tra un certo intervallo di valori.

Se corro una query con < = e> = operatori: SELECT * FROM table where ordertype <= 'ZAAA' OR ordertype >= 'ZZZZ'; poi mi 0 risultati. Questa è la risposta giusta.

Tuttavia, se io non uso TRA: SELECT * FROM table where ordertype NOT BETWEEN 'ZAAA' AND 'ZZZZ'; , allora si dà colpi multipli.

La mia comprensione è che entrambe le sintassi dovrebbero dare lo stesso risultato ma non lo sono. Cosa mi manca? Motivo che desidero utilizzare NON TRA, perché molto del nostro codice esistente ha già questa sintassi e non voglio cambiarlo senza capirne i motivi.

Grazie.


Grazie per tutti quelli che hanno pubblicato. Ho eseguito nuovamente le query e dopo aver corretto "OR" nella prima query, i risultati sono gli stessi. Ho ancora la domanda sul perché l'ordinamento dei caratteri Oracle non lo riconosce come previsto, ma la mia domanda relativa alla differenza tra NOT BETWEEN e <> era un falso allarme. Mi scuso per la confusione.

+0

Le mie scuse per l'errore nella mia domanda sopra. La prima query che intendevo scrivere era ordertype <= 'ZAAA' OR ordertype> = 'ZZZZ' – user3208146

+0

Grazie per tutti quelli che hanno pubblicato. Ho eseguito nuovamente le query e dopo aver corretto "OR" nella prima query, i risultati sono gli stessi. Ho ancora la domanda sul perché l'ordinamento dei caratteri Oracle non lo riconosce come previsto, ma la mia domanda che riguarda la differenza tra NOT BETWEEN e <> era un falso allarme. – user3208146

+1

Ora, dopo aver modificato 'and' in un' o', sono abbastanza convinto che entrambe le dichiarazioni restituiscano effettivamente gli stessi record. Potresti eseguire http://sqlfiddle.com/#!4/d8ac4/1 e comunicarci quali documenti vengono restituiti. Inoltre, fai un 'select dump (ordertype) dalla tabella dove ordertype NON TRA 'ZAAA' E 'ZZZZ';' e pubblica il risultato. –

risposta

10
SELECT * FROM table where ordertype <= 'ZAAA' AND ordertype >= 'ZZZZ'; 

Nessun stringa può essere < = 'ZAAA' e> = 'ZZZZ'. È necessario utilizzare una disgiunzione invece:

SELECT * FROM table where ordertype < 'ZAAA' OR ordertype > 'ZZZZ'; 

BTW, dato che BETWEEN è inclusiva, NOT BETWEEN è esclusivo


Questo è un errore comune. si deve ricordare la De Morgan's Laws:

not (A and B) è lo stesso di (not A) or (not B)

Sentitevi liberi di sperimentare con questo semplice esempio vivo di convincere te stesso che questi risultati sono abbastanza coerenti: http://sqlfiddle.com/#!4/d41d8/38326


Detto questo, l'unico modo (posso vedere) Per la stringa come ZOCO per non essendo tra ZAAA e ZZZZ sarebbe:

  • avere qualche carattere nascosto dietro la Z (cioè: 'Z'||CHR(0)||'OCO')
  • o usa una localizzazione come Z -Qualcosa realtà è considerato come una lettera diversa, con un ordine di collazione di fuori del campo indicato. Non so se tali impostazioni locali esista, ma ad esempio, in Welch, LL è considerato come una singola lettera che dovrebbe essere ordinata dopo il semplice L. Vedi http://en.wikipedia.org/wiki/Alphabetical_order#Language-specific_conventions
  • o avendo homogplyphs come 0, o О invece di O nei dati.
+4

(un suono lontano di un facepalm) 30 anni di programmazione exp, una laurea in informatica, eppure non riuscivo a riconoscerlo. :-) Un chiaro sintomo di me stanco. +1 per una risposta ben spiegata. – nop77svk

+0

Ciao Sylvain, grazie per avermelo segnalato - Ho corretto la mia prima domanda - Sto cercando di interrogare dove ordertype <'ZAAA' o ordertype> 'ZZZZ'. Detto questo, non ho capito il commento sulla legge di DeMorgan. NON TRA 'ZAAA' E 'ZZZZ' in base al tuo commento sopra è tradotto come (NON ordetype> 'ZAAA') O (NON ordertype <'ZZZZ'). ZOCO darebbe per quello (falso) o (falso) - quindi non dovrebbe restituire ZOCO come risultato da quella query. – user3208146

+0

@ user3208146 Mi dispiace, non posso dirti molto di più: se "ZOCO" TRA "ZAAA" E "ZZZZ" è _false_ le uniche spiegazioni che mi sono venute in mente sono quelle che ho dato nel seconda parte della mia risposta.O un po 'di carattere nascosto - o una collazione considerando il digrafo 'ZO' come lettera separata - o gli omogei. –

2

La tua comprensione del fatto che entrambe le affermazioni sono uguali non è corretta. NOT BETWEEN non viene valutato nel modo in cui stai pensando. Restituisce semplicemente i risultati che non rientrano nella valutazione di BETWEEN per i parametri.

se controlli la documentazione Oracle per TRA, si dice -

The value of 

expr1 NOT BETWEEN expr2 AND expr3 
is the value of the expression 

NOT (expr1 BETWEEN expr2 AND expr3) 
+1

No, 'NOT BETWEEN' non dovrebbe restituire tutti i record. I record compresi tra 'ZAAA' e' ZZZZ' (come 'ZBCD') non verrebbero restituiti in entrambe le istruzioni. –

+1

Sì, hai ragione! – Incognito

+0

Grazie Rene. Quindi nel mio esempio, ZOCO è tra ZAAA e ZZZZ basato su ordinamento di caratteri Oracle, quindi NON TRA non dovrebbe restituire ZOCO, giusto? – user3208146

2

Se non è tra i valori, deve essere o < O>, non è AND.

2

Nella prima interrogazione, si chiede per i record che sono al tempo stesso meno di 'ZAAA'e anche maggiore di 'ZZZZ'. Naturalmente, non esiste un tale valore che soddisfi entrambi i requisiti, quindi vengono restituiti zero record.

Nella seconda interrogazione, si chiede per i record, che sono sia meno di 'ZAAA'o maggiore di 'ZZZZ' (cioè non tra questi confini [not between...]). Esiste la possibilità che tali documenti esistano e, come dimostra la tua dichiarazione scelta, ci sono effettivamente tali documenti, che vengono restituiti dalla dichiarazione.

+0

Non avevo scritto correttamente la mia domanda. La prima query dovrebbe essere ordertype <'ZAAA' OR ordertype> 'ZZZZ' e il secondo tipo di ordine NON TRA 'ZAAA' E 'ZZZZ'. – user3208146