Ignorando l'approccio corretto
per un momento, il motivo è che stai usando il cfsqltype
errato per i parametri. Quindi stai effettivamente inviando valori diversi al database (e di conseguenza eseguendo un confronto diverso) di quanto stai pensando. Di conseguenza, la query non riesce a trovare alcun record corrispondente. Ecco perché il tuo grafico è vuoto.
Usando cf_sql_timestamp
stai convertendo il "valore" in un oggetto data/ora completo. Tuttavia, YEAR() restituisce solo un numero di quattro cifre. Quindi stai confrontando mele e arance. Concettualmente, la tua query sta effettivamente facendo questo:
WHERE 2014 = {ts '2009-02-13 23:31:30'}
Il motivo per cui non genera un errore è che i valori di data/ora sono archiviati internamente come numeri. Quindi stai effettivamente confrontando un numero piccolo (es. anno) con un numero davvero grande (es. data/ora). Ovviamente il valore della data sarà molto più grande, quindi non corrisponderà quasi mai al numero dell'anno. Ancora una volta, concettualmente la tua query sta facendo questo:
WHERE 2014 = 1234567890
Poiché cfsqltype è opzionale, molte persone pensano che non sia molto importante, ma lo è.
-
Convalida: Oltre agli altri vantaggi, cfqueryparam convalida il "valore" fornito in base a
cfsqltype
(data, data e ora, numero, ecc.). Ciò si verifica prima lo sql viene mai inviato al database. Quindi, se l'input non è valido, non sprechi una chiamata al database. Se ometti cfsqltype, o usi semplicemente la stringa ie predefinita, perdi quella convalida extra. -
Precisione La selezione del corretto cfsqltype assicura di inviare il valore corretto al database. Come dimostrato in precedenza, l'utilizzo del tipo errato può causare l'invio da parte di CF del valore errato al database.
Il
cfsqltype
assicura inoltre che i valori vengano inviati al database in un formato non ambiguo che il database interpreterà nel modo previsto. Tecnicamente potresti inviare tutto al database una stringa. Tuttavia, ciò costringe il database a eseguire la conversione implicita (solitamente indesiderabile).Con la conversione implicita, l'interpretazione delle stringhe è lasciata interamente al database e potrebbe non fornire sempre la risposta che ti aspetteresti. L'invio di date come stringhe, anziché come oggetti data, ne è un ottimo esempio. In che modo il database corrente interpreterà una stringa di data come "05/04/2014"? Come il 5 aprile o il 4 maggio? Dipende. Modificare il database o le impostazioni del database e il risultato potrebbe essere completamente diverso.
L'unico modo per garantire risultati coerenti è specificare il cfsqltype appropriato. Deve corrispondere al tipo di dati della colonna/funzione di confronto o almeno a un tipo equivalente. Nel caso di YEAR()
, restituisce un numero di quattro cifre. Quindi dovresti usare cf_sql_integer
, come Adrian ha menzionato i commenti
. Lo stesso vale per le tue MESE() confronto.
WHERE Year(ColumnName) = <cfqueryparam value="2014" cfsqltye="CF_SQL_INTEGER">
AND Month(ColumnName) = <cfqueryparam value="11" cfsqltye="CF_SQL_INTEGER">
Detto questo, Suggerimento di Dan
è il modo migliore per eseguire confronti di date. Quel paradigma
è più compatibile con l'indice e funziona indipendentemente dal fatto che la colonna di destinazione contenga una data (solo) o una data e un'ora. Nota l'uso di cf_sql_date
nel suo esempio.
cf_sql_timestamp
- invia sia una data che un'oracf_sql_date
- invia solo una data. il valore dell'ora viene troncato