Redshift - Converting UTC data to other timezones - sql

I am trying to convert data from UTC to various European timezones. I am using a case statement and find only the first condition in the case statement is executed while the other conditions are not checked.
SELECT sale_id,appointment_time,timezone,
case when timezone = 'EDT' then (appointment_time + interval '-4' HOUR * 1)
when timezone = 'BST' then (appointment_time + interval '1' HOUR * 1)
when timezone = 'CEST' then (appointment_time + interval '2' HOUR * 1)
when timezone = 'EEST' then (appointment_time + interval '3' HOUR * 1)
when timezone = 'MSK' then (appointment_time + interval '3' HOUR * 1)
when timezone = 'WEST' then (appointment_time + interval '1' HOUR * 1)
else null
end as NewTime
FROM sales
Could anyone advice as to where am I going wrong. Thanks

you missed else just add before end and use dateadd function
SELECT sale_id,appointment_time,timezone,
case when timezone = 'EDT' then dateadd(h,-4,appointment_time)
when timezone = 'BST' then dateadd(h,1,appointment_time)
--------------
--------------
else null
end as NewTime
FROM sales

Why don't you use built in convert_timezone function. It would be faster since you don't need to use a case
SELECT sale_id, appointment_time, timezone,
convert_timezone(timezone, appointment_time) as NewTime
FROM sales

Related

Trying to get HH:MM:SS from milliseconds in Presto

I'm trying to convert milliseconds to format HH:MM:SS or MM:SS, but I keep getting the same error.
Here's the error:
java.sql.SQLException: [Simba][AthenaJDBC](100071) An error has been thrown from the AWS Athena client. SYNTAX_ERROR: line 5:19: Unexpected parameters (time, varchar(5)) for function date_format. Expected: date_format(timestamp with time zone, varchar(x)) , date_format(timestamp, varchar(x)) [Execution ID: 89bfd858-9992-439f-ad84-b59bfd1cbde8]
Here's my code:
SELECT
column_a,
round(AVG((milliseconds) / 1000)) AS Seconds,
(case when milliseconds/1000 < 60 * 60
then time '00:00:00' + milliseconds * interval '1' second, '%i:%s'
else time '00:00:00' + milliseconds * interval '1' second, '%H:%i:%s'
end) as hhmmss,
round((AVG((column_b)) / 1099511627776),2) AS b,
COUNT(column_c) AS c
FROM
table
GROUP BY
column_a
Tried with this one as well
(case when milliseconds/1000 < 60 * 60
then date_format(time '00:00:00' + milliseconds * interval '1' second, '%i:%s')
else date_format(time '00:00:00' + milliseconds * interval '1' second, '%H:%i:%s')
end) as hhmmss
Any help, please?
You can just cast your time to timestamp:
select date_format(cast(time '00:00:00' + 23 * interval '1' second as timestamp), '%H:%i:%s')
Output:
_col0
00:00:23
Note that this will work only if you have less than 24 hours interval in your milliseconds, otherwise you will need to do math yourself and concat results into desired string.
P.S. Should not milliseconds * interval '1' second be (milliseconds/1000) * interval '1' second?

How to transpose in SQL?

This is my SQL query:
'{select id,value,
case when temp.country-id=2 then
interval 4 hour + cast(time as time ) else
interval 3 hour + cast(time as time ) end as TIME
from temp}'
This is the output I am getting for above query:
I want this output using SQL:

operator does not exist: integer + interval

I have next part of query:
AND date_part('day', some_date::date - first_day::date + interval '1 day') = some_daye
and I am getting next error:
ERROR: operator does not exist: integer + interval
How I can cast 'some_date - first_day' to interval?
Subtracting a date from a date yields an integer.
An integer cannot be cast to an interval.
Cast either of your date values to timestamp to get an interval.
e.g. AND date_part('day', some_date::timestamp - first_day + interval '1 day') = some_daye
Or you could simplify the entire expression as AND some_date - first_day + 1 = some_daye

Add additional column in a SELECT statement based on values of other columns PSQL

I have a table of driver licenses per person and know when a person acquired the drivers license. The validity of the drivers license can either be X days from the day you acquired it or a specific date.
acquired relative specific_date valid_type expiration_date
----------------------------------------------------------------------------------
2015-02-05 500 null days
2015-02-05 null 2016-03-05 date
2015-02-05 200 null days
2015-02-05 null 2016-02-22 date
My query right now would be:
SELECT acquired,
relative_date,
specific_date,
valid_type
FROM person_drivers_license
WHERE (valid_type = 'days'
AND (EXTRACT(epoch
FROM acquired) - EXTRACT(epoch
FROM now()))/86400 + relative_date > 0)
OR (valid_type = 'DATE'
AND specific_date >= now()));
I am trying to add an expiration_date column with the select statement above. If it is a specific date, just take the date and put it in expiration_date and if it is a relative date, calculate the expiration date with the help of the acquired date. Is this possible in PSQL?
First - there is a simpler way to do date math in postgres. You can use something like:
acquired + relative_date * interval '1 day' >= current_date
or
acquired + relative_date >= current_date
-- any integer can be treated as interval in days for date mathematics is SQL
For the question - try one of this:
CASE WHEN valid_type = 'days'
THEN acquired + relative_date * interval '1 day'
WHEN valid_type = 'date'
THEN specific_date
--ELSE ??? you may specify something here
END
or
COALESCE(specific_date, acquired + relative_date * interval '1 day')
The query may look like:
SELECT acquired,
relative_date,
specific_date,
valid_type,
COALESCE(specific_date, acquired + relative_date * interval '1 day') as valid_date
FROM person_drivers_license
WHERE COALESCE(specific_date, acquired + relative_date * interval '1 day') >= current_date
Try this:
SELECT acquired,
relative_date,
specific_date,
valid_type
CASE valid_type
WHEN 'days' THEN acquired + relative_date
WHEN 'date' THEN specific_date
ELSE NULL
END AS expiration_date
FROM person_drivers_license;
You don't need pl/sql
SELECT acquired,
relative_date,
specific_date,
valid_type,
CASE WHEN specific date = "date" -- starts here
THEN specific date
ELSE acquired + cast('1 months' as interval)END
AS expiration_date -- end here
FROM person_drivers_license
WHERE (valid_type = 'days'
AND (EXTRACT(epoch
FROM acquired) - EXTRACT(epoch
FROM now()))/86400 + relative_date > 0)
OR (valid_type = 'DATE'
AND specific_date >= now()));

How to use CASE together with date INTERVAL?

I want to have this query:
SELECT DATE(DATE_SUB(DATE('2010-09-10'), (CASE DATETYPE WHEN 'H' THEN INTERVAL 1 WEEK ELSE INTERVAL 1 YEAR END CASE))) AS wdt
MySQL says it's invalid
also I have tried
SELECT _DATE AS wdt
UNION ALL
CASE DATETYPE
WHEN 'H' THEN SELECT DATE(DATE_SUB(_DATE, INTERVAL 1 YEAR)) AS wdt ;
ELSE SELECT DATE(DATE_SUB(DATE('2010-09-10'), INTERVAL 1 WEEK )) AS wdt;
END CASE;
UNION ALL
SELECT DATE(DATE_SUB(_DATE, INTERVAL 2 WEEK)) AS wdt
which doesn't work also, error in query syntax.
How can I select interval 1 year for dates that are Holidays.
Using two DATE_SUB operations would work:
SELECT IF (DATETYPE = 'H',
DATE_SUB(DATE('2010-09-10'), INTERVAL 1 WEEK),
DATE_SUB(DATE('2010-09-10'), INTERVAL 1 YEAR))
as wdt;