2009-07-07 13 views
5

Ho un problema con la query di seguito in PostgresSUBSTR non funziona con tipo di dati "timestamp" in Postgres 8.3

SELECT u.username,l.description,l.ip,SUBSTRING(l.createdate,0,11) as createdate,l.action 
FROM n_logs AS l LEFT JOIN n_users AS u ON u.id = l.userid 
WHERE SUBSTRING(l.createdate,0,11) >= '2009-06-07' 
    AND SUBSTRING(l.createdate,0,11) <= '2009-07-07'; 

ho sempre usato la query precedente in una versione precedente di postgres e ha funzionato al 100%. Ora, con la nuova versione di posgres mi dà errori come di seguito

**ERROR: function pg_catalog.substring(timestamp without time zone, integer, integer) does not exist 
LINE 1: SELECT u.username,l.description,l.ip,SUBSTRING(l.createdate,... 
              ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.** 

suppongo che abbia qualcosa a che fare con tipi di dati, che i dati sono un fuso orario e che stringa supportano solo i tipi di dati stringa, ora la mia domanda è che cosa posso fare circa la mia domanda in modo che i miei risultati verrebbero?

risposta

6

La soluzione esplicita a il tuo problema consiste nel trasmettere il datetime in stringa.

..., SUBSTRING (l.createdate :: varchar, ...

Ora, questo non è affatto una buona pratica di utilizzare il risultato per confrontare le date.

Così, il buona soluzione per il vostro bisogno è quello di modificare la tua ricerca utilizzando i esplicite datetime manipulation, comparison e formatting funzioni, come l'estratto() e to_char()

avresti per modificare la tua ricerca per avere una clausola come

l.createdate::DATE >= '2009-06-07'::DATE 
AND l.createdate::DATE < '2009-07-08'::DATE; 

o una delle alternative seguenti

+0

non sapeva di questo, ma questo risolto il mio problema – Roland

5
SELECT u.username, l.description, l.ip, 
     CAST(l.createdate AS DATE) as createdate, 
     l.action 
FROM n_logs AS l 
LEFT JOIN 
     n_users AS u 
ON  u.id = l.userid 
WHERE l.createdate >= '2009-06-07'::TIMESTAMP 
     AND l.createdate < '2009-07-07'::TIMESTAMP + '1 DAY'::INTERVAL 
+0

Eh, +1 questo ha più senso, non ho letto la query fino alla fine! (/ me punisce me stesso). –

1

Una variazione sulla risposta della Quassnoi (che si dovrebbe davvero accettare al posto di questo.):

SELECT 
    u.username, 
    l.description, 
    l.ip, 
    CAST(l.createdate AS DATE) as createdate, 
    l.action 
FROM 
    n_logs AS l 
LEFT JOIN 
    n_users AS u 
ON 
    (u.id = l.userid) 
WHERE 
    l.createdate::DATE BETWEEN '2009-06-07'::DATE AND '2009-07-07'::DATE 
+0

@ Millen: non è sargibile – Quassnoi

+0

Ma è corretto e leggibile. –

1

io non sono sicuro di quello che vuoi per raggiungere, ma fondamentalmente la "sottostringa" sui datatype delle date non è molto ben definita, in quanto dipende dal formato esterno di tali dati.

Nella maggior parte dei casi è necessario utilizzare le funzioni extract() o to_char().

In genere, per restituire i dati si desidera to_char() e per le operazioni su di esso (incluso il confronto) - extract(). Ci sono alcuni casi in cui questa regola generale non si applica, ma questi sono di solito segni di una struttura dei dati non ben pensata.

Esempio:

# select to_char(now(), 'YYYY-MM-DD'); 
    to_char 
------------ 
2009-07-07 
(1 row) 

Per estratto scriviamo una semplice query che elenca tutti gli oggetti creati dopo 8:

select * from objects where extract(hour from created) >= 20; 
+0

Un buon punto sull'infinizione della sottostringa sui tipi di data –

0

Se si utilizza PostgreSQL, si riceverà:

select('SUBSTRING(offer.date_closed, 0, 11)') 

substr di funzione (timestamp senza fuso orario integ er intero) non lo fa esiste

Usa:

select('SUBSTRING(CONCAT(offer.date_closed, \'\'), 0, 11)') 
Problemi correlati