Convert varchar dates (BC & AD) to date format in sql - sql

Dates are stored like this in another table as varchars
select wkdocre from works;
wkdocre
-------------
+1654/12/31
+1706/12/31
+1667/12/31
-0332/12/31
-0332/12/31
-1295/12/31
And I want to insert these dates into another table with an attribute that is of type date like this
update ns_works set wor_workcreationdate=(select wkdocre from works where wor_workcreationdate=wkdocre);
I get this error
ERROR: operator does not exist: ns_workcreationdate = dateofcreation
LINE 1: ...lect wkdocre from works where wor_workcreationdate=wkdocre);
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Thank-you
Desired results
select wor_creationdate from ns_works;
wor_creationdate
-------------
1654/12/31
1706/12/31
1667/12/31
-0332/12/31
-0332/12/31
-1295/12/31

You need explicit conversion; try something like that:
... SET wor_workcreationdate =
to_date(
(select wkdocre
from works
where wor_workcreationdate = to_date(wkdocre, 'YYYY/MM/DD')),
'YYYY/MM/DD'
)
Writing years BC with a minus sign is incorrect though; PostgreSQL will interpret -1295 as 1296 BC, since year 0 is actually 1 BC. You might want to fix your works table and use YYYY/MM/DD BC as format specifier.

Related

Treat TO_NUMBER() invalid format errors as NULL

I have a string column which usually contains integers in two formats... zero-padded, and not:
5
05
I want to sort based on these values numerically. To do that I do something like:
SELECT * FROM things ORDER BY TO_NUMBER(num, '0000');
This works fine, but sometimes there is invalid data, like abc, or !## in this column. Postgres becomes unhappy with me:
ERROR: invalid input syntax for type numeric: " "
What I'd like to do is treat invalid values/failures of TO_NUMBER() as NULL so that they are sorted accordingly. Is this possible? Or, some other alternative?
If you are using PostgreSQL, you can use this query:
SELECT * FROM things ORDER BY
TO_NUMBER((case when num ~ '^[0-9\.]+$' THEN num else '0' end),'0000');

Getting an error when using CONCAT in BigQuery

I'm trying to run a query where I combine two columns and separate them with an x in between.
I'm also trying to get some other columns from the same table. However, I get the following error.
Error: No matching signature for function CONCAT for argument types: FLOAT64, FLOAT64. Supported signatures: CONCAT(STRING, [STRING, ...]); CONCAT(BYTES, [BYTES, ...]).
Here is my code:
SELECT
CONCAT(right,'x',left),
position,
numbercreated,
Madefrom
FROM
table
WHERE
Date = "2018-10-07%"
I have tried also putting a cast before but that did not work.
SELECT Concast(cast(right,'x',left)), position,...
SELECT Concast(cast(right,'x',left)as STRING), position,...
Why am I getting this error?
Are there any fixes?
Thanks for the help.
You need to cast each value before the concat():
SELECT CONCAT(CAST(right as string), 'x', CAST(left as string)),
position, numbercreated, Madefrom
FROM table
WHERE Date = '2018-10-07%';
If you want a particular format, then use the FORMAT() function.
I also doubt that your WHERE will match anything. If Date is a string, then you probably want LIKE:
WHERE Date LIKE '2018-10-07%';
More likely, you should use the DATE function or direct comparison:
WHERE DATE(Date) = '2018-10-07'
or:
WHERE Date >= '2018-10-07' AND
Date < '2018-10-08'
Another option to fix your issue with CONCAT is to use FROMAT function as in below example
#standardSQL
WITH `project.dataset.table` AS (
SELECT 1.01 AS `right`, 2.0 AS `left`
)
SELECT FORMAT('%g%s%g', t.right, 'x', t.left)
FROM `project.dataset.table` t
result will be
Row f0_
1 1.01x2
Note: in above specific example - you could use even simpler statement
FORMAT('%gx%g', t.right, t.left)
You can see more for supporting formats
Few recommendations - try not to use keywords as a column names/aliases. If for some reason you do use - wrap such with backtick or prefix it with table name/alias
Yet another comment - looks like you switched your values positions - your right one is on left side and left one is on right - might be exactly what you need but wanted to mention
Try like below by using safe_cast:
SELECT
CONCAT(SAFE_CAST( right as string ),'x',SAFE_CAST(left as string)),
position,
numbercreated,
Madefrom
FROM
table
WHERE
Date = '2018-10-07'

Postgresql ERROR: operator does not exist: date ~~ unknown

When I do this query, I have no problems:
SELECT a.value, b.label AS campo, 'date' AS tipo
FROM contenido.field_value_textarea a
JOIN estructura.field b ON a.field=b.id
WHERE a.value LIKE '%aaa%'
contenido.field_value_textarea is character varying(2000)
But if I try to select from:
contenido.field_value_fecha which type is date I got this error message:
ERROR: operator does not exist: date ~~ unknown
What I'm trying to do is searching between different tables, each query select FROM it's table. Some tables use text values, textarea values, integer values, and it works, but when the value is date all fails. What can I do?
EDIT: By the way, my date values are like this: 2009-05-01
The ~~ operator is actually the LIKE operator.
You are trying to use an expression that looks like:
contenido.field_value_fecha.value LIKE '%aaaa%'
That is, you're trying to compare a date with a string (which, without the adequate context, is considered to be of type 'unknown'), and decide if the date looks like something.
If you actually want to do such a comparison, you need to convert the date to a string, which can be done by means of:
contenido.field_value_fecha.value::text LIKE '%aaaa%'
or (using standard SQL):
CAST(contenido.field_value_fecha.value AS text) LIKE '%aaaa%'
This will be syntactically correct... Whether it is meaningful or not, is a different part of the story.

sqlldr - how to use if/then logic on a field?

I am loading a particular field that has date values. However, some of them are not complete... for example the values look like this
START_DATE
'2015-06-12'
'2016-12-24'
'2015-02' <--- this is what causes an error
'2016-01-03'
I have tried solving this by combining NULLIF with a LENGTH() function like so, but this is not allowed:
Start_date NULLIF LENGTH(:start_date)<10 to_date .....
this returns the error
Expecting positive integer or column name, found keyword length.
My main objective is to load dates that are of a proper format, and load NULL otherwise. What is the easiest way to do this within the ctl file? Can I avoid creating a custom function?
Say I have a table like this:
create table dateTable(START_DATE date)
and I need to load this file, where I want to insert NULL where the string does not match my pattern
'2016-12-28'
'2016-12-'
'2016-12-31'
I can add some logic in my ctl file to check the length of the string to load this way:
load data
infile dateTable.csv
into TABLE dateTable
fields enclosed by "'"
( START_DATE "to_date(case when length(:START_DATE) = 10 then :START_DATE end, 'yyyy-mm-dd')"
)
This simply checks the length of the string, but you can edit it anyway you need to build your own logic; notice that CASE gives NULL when no condition is matched, so this is equivalent to case when length(:START_DATE) = 10 then :START_DATE else NULL end.
This gives the following result:
SQL> select * from dateTable;
START_DATE
----------
28-DEC-16
31-DEC-16
In oracle, you can verify a string to make sure that is it valid date or not. Please Check IsDate function.

Search Through All Between Values SQL

I have data following data structure..
_ID _BEGIN _END
7003 99210 99217
7003 10225 10324
7003 111111
I want to look through every _BEGIN and _END and return all rows where the input value is between the range of values including the values themselves (i.e. if 10324 is the input, row 2 would be returned)
I have tried this filter but it does not work..
where #theInput between a._BEGIN and a._END
--THIS WORKS
where convert(char(7),'10400') >= convert(char(7),a._BEGIN)
--BUT ADDING THIS BREAKS AND RETURNS NOTHING
AND convert(char(7),'10400') < convert(char(7),a._END)
Less than < and greater than > operators work on xCHAR data types without any syntactical error, but it may go semantically wrong. Look at examples:
1 - SELECT 'ab' BETWEEN 'aa' AND 'ac' # returns TRUE
2 - SELECT '2' BETWEEN '1' AND '10' # returns FALSE
Character 2 as being stored in a xCHAR type has greater value than 1xxxxx
So you should CAST types here. [Exampled on MySQL - For standard compatibility change UNSIGNED to INTEGER]
WHERE CAST(#theInput as UNSIGNED)
BETWEEN CAST(a._BEGIN as UNSIGNED) AND CAST(a._END as UNSIGNED)
You'd better change the types of columns to avoid ambiguity for later use.
This would be the obvious answer...
SELECT *
FROM <YOUR_TABLE_NAME> a
WHERE #theInput between a._BEGIN and a._END
If the data is string (assuming here as we don't know what DB) You could add this.
Declare #searchArg VARCHAR(30) = CAST(#theInput as VARCHAR(30));
SELECT *
FROM <YOUR_TABLE_NAME> a
WHERE #searchArg between a._BEGIN and a._END
If you care about performance and you've got a lot of data and indexes you won't want to include function calls on the column values.. you could in-line this conversion but this assures that your predicates are Sargable.
SELECT * FROM myTable
WHERE
(CAST(#theInput AS char) >= a._BEGIN AND #theInput < a.END);
I also saw several of the same type of questions:
SQL "between" not inclusive
MySQL "between" clause not inclusive?
When I do queries like this, I usually try one side with the greater/less than on either side and work from there. Maybe that can help. I'm very slow, but I do lots of trial and error.
Or, use Tony's convert.
I supposed you can convert them to anything appropriate for your program, numeric or text.
Also, see here, http://technet.microsoft.com/en-us/library/aa226054%28v=sql.80%29.aspx.
I am not convinced you cannot do your CAST in the SELECT.
Nick, here is a MySQL version from SO, MySQL "between" clause not inclusive?