Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract year from date within WHERE clause

I need to include EXTRACT() function within WHERE clause as follow:

SELECT * FROM my_table WHERE EXTRACT(YEAR FROM date) = '2014';

I get a message like this:

pg_catalog.date_part(unknown, text) doesn't exist** 
SQL State 42883

Here is my_table content (gid INTEGER, date DATE):

  gid  |    date
-------+-------------
  1    | 2014-12-12
  2    | 2014-12-08
  3    | 2013-17-15

I have to do it this way because the query is sent from a form on a website that includes a 'Year' field where users enter the year on a 4-digits basis.

like image 886
wiltomap Avatar asked Dec 12 '14 09:12

wiltomap


People also ask

Can we use extract in where clause?

With the help of following MySQL query, we can apply EXTRACT() function with WHERE clause on the dates stored in a table.

How do I get the year from a date in SQL?

The EXTRACT() function returns a number which represents the year of the date. The EXTRACT() function is a SQL standard function supported by MySQL, Oracle, PostgreSQL, and Firebird. If you use SQL Server, you can use the YEAR() or DATEPART() function to extract the year from a date.

How do I extract the year from a date in R?

To extract the year from the column, we will create a dataframe with date columns and then separate the year from DateTime using format() methods and extract the year and convert to a numeric format.


2 Answers

The problem is that your column is of data type text, while EXTRACT() only works for date / time types.

You should convert your column to the appropriate data type.

ALTER TABLE my_table ALTER COLUMN date TYPE date;

That's smaller (4 bytes instead of 11 for the text), faster and cleaner (disallows illegal dates and most typos).
If you have non-standard format add a USING clause with a conversion expression. Example:

  • Alter character field to date

Also, for your queries to be fast with a plain index on date you should rather use sargable predicates. Like:

SELECT * FROM my_table
WHERE    date >= '2014-01-01'
AND      date <  '2015-01-01';

Or, to go with your 4-digit input for the year:

SELECT * FROM my_table
WHERE    date >= to_date('2014', 'YYYY')
AND      date <  to_date('2015', 'YYYY');

You could also be more explicit:

to_date('2014' || '0101', 'YYYYMMNDD')

Both produce the same date '2014-01-01'.

Aside: date is a reserved word in standard SQL and a basic type name in Postgres. Don't use it as identifier.

like image 65
Erwin Brandstetter Avatar answered Oct 05 '22 20:10

Erwin Brandstetter


This happens because the column has a text or varchar type, as opposed to date or timestamp. This is easily reproducible:

SELECT 1 WHERE extract(year from '2014-01-01'::text)='2014';

yields this error:

ERROR: function pg_catalog.date_part(unknown, text) does not exist
LINE 1: SELECT 1 WHERE extract(year from '2014-01-01'::text)='2014';
^ HINT: No function matches the given name and argument types. You might need to add explicit type casts.

extract or is underlying function date_part does not exist for text-like datatypes, but they're not needed anyway. Extracting the year from this date format is equivalent to getting the 4 first characters, so your query would be:

SELECT * FROM my_table WHERE left(date,4)='2014';
like image 43
Daniel Vérité Avatar answered Oct 05 '22 20:10

Daniel Vérité