Interchange String with Date in query - sql

I am running the below query. I would like to make this query more dynamic, however, so I would like to use the 2nd query instead.
SELECT X
FROM Y
WHERE Z
and file_created_date = '12/18/2016'
SELECT X
FROM Y
WHERE Z
and file_created_date = SELECT date(GETDATE()-2)
The 2nd query returns an error around the Select of
SELECT date(GETDATE()-2)

GETDATE() isn't available in postgres. You can however use current_date i.e.
... and file_created_date = current_date - 2

Postgres supports interval offsets for dates:
where Z and
file_created_date = current_date - interval '2 day'
If file_created_date also has a time component, then you should take that into account:
where Z and
file_created_date > current_date - interval '3 day' and
file_created_date <= current_date - interval '2 day'

Related

How to get generate_series() function in Redshift to result in just dates NOT date-time

Is there a way to remove the timestamp on the result set?
This is the query I am running in Redshift:
SELECT CURRENT_DATE - (i * interval '1 day') as dates
FROM generate_series(0,7) i
ORDER BY 1;
This is the result:
1
2020-10-21T00:00:00.000Z
2
2020-10-22T00:00:00.000Z
3
2020-10-23T00:00:00.000Z
4
2020-10-24T00:00:00.000Z
5
2020-10-25T00:00:00.000Z
6
2020-10-26T00:00:00.000Z
7
2020-10-27T00:00:00.000Z
8
2020-10-28T00:00:00.000Z
Just cast:
SELECT cast(current_date - i * interval '1 day' as date) as dates
FROM generate_series(0, 7) i
ORDER BY 1;
Or:
SELECT (current_date - i * interval '1 day')::date as dates
FROM generate_series(0, 7) i
ORDER BY 1;

How to select all rows created in the last hour?

My query is
SELECT * FROM email_operation WHERE cdate = CURRENT_DATE and ctime >= (NOW() - INTERVAL '1 hour' )
to select all rows created at the last hour but it doesn't work. It throws an error at >=
SELECT * FROM email_operation WHERE cdate = CURRENT_DATE and ctime >= (NOW() - INTERVAL '12 hour' )
> ERROR: operator does not exist: time without time zone >= timestamp with time zone
LINE 1: ..._operation WHERE cdate = CURRENT_DATE and ctime >= (NOW() ...
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
> Time: 0.001s
Apparently ctime is a time column, so you can't compare it with a timestamp (which is what the error message tells you). You need to use current_time instead:
and ctime >= current_time - interval '1 hour'
Note that this won't work properly around midnight.
It seems you have split up date and time into two columns (which is a bad idea), but you can combine them to compare a timestamp:
and cdate + ctime >= current_timestamp - interval '1 hour'
If you want results in the past hour and you have separated the date and time components, then one method is:
WHERE (cdate + ctime) >= NOW() - INTERVAL '1 hour'
Note that this will even work between midnight and 1:00 a.m. Sadly, it probably won't use indexes. That might be an issue if you have lots of data. Here is one method that will at least use an index on cdate:
WHERE cdate IN (CURRENT_DATE, CURRENT_DATE - INTERVAL '1 day') AND
( (cdate + ctime) >= NOW() - INTERVAL '1 hour' )
where (cdate + ctime)::timestamp(0) >= (now() - interval '1 hour')

Having trouble with SQL Interval

I need to get the sum of data from a particular date going back one year. But I am having difficult with the Interval
Select 0 - sum(l.icdetailquantity )
from inventoryline l
where l.icmasterid = 'WAD185967E' and l.icdetailtranstype = 5
and l.icdetaildate <= '01-Jan-2019' and l.icdetaildate > Now() - interval '1 year'
This works as expected but I need to passs a date not use Now()
Select 0 - sum(l.icdetailquantity )
from inventoryline l
where l.icmasterid = 'WAD185967E' and l.icdetailtranstype = 5
and l.icdetaildate <= '01-Jan-2019' and l.icdetaildate > '01-Jan-2019' - interval '1 year'
the second SQl give an error
ERROR: invalid input syntax for type interval: "01-Jan-2019"
LINE 4: ...detaildate <= '01-Jan-2019' and l.icdetaildate > '01-Jan-20...
You're trying to subtract a year from a string. This does not work, you have to first cast youru string to a date object using:
to_date(date_string,format)
Example that will work for you:
to_date('01-Jan-2019', 'DD-Mon-YYYY') - interval '1 year'
http://www.postgresqltutorial.com/postgresql-to_date/
Have you tried with
Select 0 - sum(l.icdetailquantity )
from inventoryline l
where l.icmasterid = 'WAD185967E'
and l.icdetailtranstype = 5
and l.icdetaildate <= date '2019-01-01'
and l.icdetaildate > date '2019-01-01' - interval '1 year'
From the documentation I'm looking at (https://www.postgresql.org/docs/current/functions-datetime.html) the "date" keyword seems to be necessary.

SQL: Select average value of column for last hour and last day

I have a table like below image. What I need is to get average value of Volume column, grouped by User both for 1 hour and 24 hours ago. How can I use avg with two different date range in single query?
You can do it like:
SELECT user, AVG(Volume)
FROM mytable
WHERE created >= NOW() - interval '1 hour'
AND created <= NOW()
GROUP BY user
Few things to remember, you are executing the query on same server with same time zone. You need to group by the user to group all the values in volume column and then apply the aggregation function like avg to find average. Similarly if you need both together then you could do the following:
SELECT u1.user, u1.average, u2.average
FROM
(SELECT user, AVG(Volume) as average
FROM mytable
WHERE created >= NOW() - interval '1 hour'
AND created <= NOW()
GROUP BY user) AS u1
INNER JOIN
(SELECT user, AVG(Volume) as average
FROM mytable
WHERE created >= NOW() - interval '1 day'
AND created <= NOW()
GROUP BY user) AS u2
ON u1.user = u2.user
Use conditional aggregation. Postgres offers very convenient syntax using the FILTER clause:
SELECT user,
AVG(Volume) FILTER (WHERE created >= NOW() - interval '1 hour' AND created <= NOW()) as avg_1hour,
AVG(Volume) FILTER (WHERE created >= NOW() - interval '1 day' AND created <= NOW()) as avg_1day
FROM mytable
WHERE created >= NOW() - interval '1 DAY' AND
created <= NOW()
GROUP BY user;
This will filter out users who have had no activity in the past day. If you want all users -- even those with no recent activity -- remove the WHERE clause.
The more traditional method uses CASE:
SELECT user,
AVG(CASE WHEN created >= NOW() - interval '1 hour' AND created <= NOW() THEN Volume END) as avg_1hour,
AVG(CASE WHEN created >= NOW() - interval '1 day' AND created <= NOW() THEN Volume END) as avg_1day
. . .
SELECT User, AVG(Volume) , ( IIF(created < DATE_SUB(NOW(), INTERVAL 1 HOUR) , 1 , 0) )IntervalType
WHERE created < DATE_SUB(NOW(), INTERVAL 1 HOUR)
AND created < DATE_SUB(NOW(), INTERVAL 24 HOUR)
GROUP BY User, (IIF(created < DATE_SUB(NOW(), INTERVAL 1 HOUR))
Please Tell me about it's result :)

Date subtraction

I'd like to select all the users in our database that put their accounts on hold the day they created them. Users can only go on hold for 1 month, so the logic would be selecting users where....
day(hold_until - 1 month) = day(signup)
How can I achieve this in SQL?
Try:
SELECT *
FROM TheTable
WHERE date(singup) = date(hold_until - INTERVAL '6 months')
It depends on the RDBMS You're using, but assuming this is PostgreSQL, you can try this:
...where
day(hold_until - interval '1 month') = day(signup)
Assuming you have timestamp columns:
... WHERE (hold_until - interval '1 month')::date = singnup::date