I want to get a list of orders that are placed in a given date range, but exclude the orders placed between 2pm-10pm.
Can anyone help me to complete the below query
select *
from abc
where
date(order_created) between '2021-05-22' and '2021-05-24'
and not between <order placed between 2pm-10pm>
You can use time() to get the time part. That allows:
date(order_created) between '2021-05-22' and '2021-05-24' and
time(order_created) not between '14:00:00' and '20:00:00'
Note that this excludes both the end points. More commonly, you would want to exclude the first but keep the second:
date(order_created) between '2021-05-22' and '2021-05-24' and
(time(order_created) < '14:00:00' or
time(order_created) >= '20:00:00'
)
Try:
and EXTRACT(TIME FROM order_created) not between '14:00:00' and '22:00:00'
Note: I'm assuming your order_created column contains the time as well. FYI: in BigQuery there are two types of fields that contain date and time: Timestamp, and Datetime, so your order_created field is likely one of those two types. The SQL differs slightly between manipulating one type or the other, but the EXTRACT function works on both.
Related
I have a SQL query that includes a __DATE__ macro. A Python script replaces this macro with the current date and then the statement is executed thus giving one day's worth of data.
For the first item selected, I would like to use tblLabTestResult.CollectionDate instead of __DATE__.
I would like to include the prior 7 days instead of just the current day.
The desired output would be something similar to:
Date,Result,Total
2021-08-28,Detected,5
2021-08-28,Not Detected,9
2021-08-29,Detected,23
2021-08-29,Not Detected,6
2021-08-30,Detected,88
2021-08-30,Not Detected,26
Current query:
SELECT
'__DATE__' as Date,
tblLabTestResult.Result as Result,
Count(tblLabTestResult.Result) as Total
FROM
PncRegDb.dbo.tblLabTestResult as tblLabTestResult
WHERE
tblLabTestResult.TestName like '%cov%'
AND tblLabTestResult.TestName not like '%aoe%'
AND tblLabTestResult.TestName not like '%antibody%'
AND tblLabTestResult.CollectionDate >= '__DATE__'
AND tblLabTestResult.CollectionDate <= '__DATE__ 11:59:59 PM'
GROUP BY
tblLabTestResult.Result;
How can I change my SQL query to accommodate these requirements? I am using MS SQL Server.
You can use DATEADD() function to get the date from 7 days ago and use all dates between date-7days and date. I have updated where condition in your query below:
SELECT
'__DATE__' as Date,
tblLabTestResult.Result as Result,
Count(tblLabTestResult.Result) as Total
FROM
PncRegDb.dbo.tblLabTestResult as tblLabTestResult
WHERE
tblLabTestResult.TestName like '%cov%'
AND tblLabTestResult.TestName not like '%aoe%'
AND tblLabTestResult.TestName not like '%antibody%'
AND tblLabTestResult.CollectionDate between DATEADD(day, -7, '__DATE__') and '__DATE__ 11:59:59 PM'
GROUP BY
tblLabTestResult.Result;
A few points:
Columns that are not aggregated must be in the GROUP BY
You should be passing your date as a parameter
Best to use a half-open interval to compare dates (exclusive end-point), so #endDate is the day after the one you want
Use short, meaningful aliases to make your code more readable
It doesn't make sense to group and aggregate by the same column. If Result is a non-nullable column then Count(Result) is the same as Count(*)
If you want to group by whole days (and CollectionDate has a time component) then replace ltr.CollectionDate with CAST(ltr.CollectionDate AS date) in both the SELECT and GROUP BY
SELECT
ltr.CollectionDate as Date,
ltr.Result as Result,
COUNT(*) as Total
FROM
PncRegDb.dbo.tblLabTestResult as tblLabTestResult
WHERE
ltr.TestName like '%cov%'
AND ltr.TestName not like '%aoe%'
AND ltr.TestName not like '%antibody%'
AND ltr.CollectionDate >= #startdate
AND ltr.CollectionDate < #endDate
GROUP BY
ltr.CollectionDate, ltr.Result;
Currently I'm trying to grab the average date difference between the start and end datetime of multiple events which occur multiple times within the same month. There are four different types of Event which run for different amounts of time.
select
min(datetime) starttime,
max(datetime) endtime,
avg(endtime - min(datetime)) As avg_days,
event
from log_economy_event_point_spending a
AND datetime between '2021-01-01' AND '2021-04-30'
group by event
order by event
However, using this method, if the event occurs multiple times it takes the start of the first event, and the end of the last event. How do I write SQL code that can get the average datetime duration of different type of event?
Many thanks
Hmmm . . . I think you want:
select event,
min(datetime) as starttime, max(datetime) as endtime,
(max(datetime) - min(datetime)) / nullif(count(*) - 1, 0) As avg_days
from log_economy_event_point_spending leeps
where datetime >= '2021-01-01' and
datetime < '2021-05-01'
group by event
order by event;
This fixes the date/time arithmetic to get the average. Note the other changes:
The date comparison includes all date/time values in April, which I'm guessing is your intention. Your version eliminates values on April 30th.
The table aliases is meaningful rather than being an arbitrary letter.
You cannot re-use column aliases in the expressions in the select where the aliases are defined.
Here is what I did:
Select count(check_id)
From Checks
Where timestamp::date > '2012-07-31'
Group by 1
Is it right to do it like I did or is there a better way? Should/could I have used the DateDIFF function in my WHERE clause? Something like: DATEDIFF(day, timestamp, '2012/07/31') > 0
Also, I need to figure out how I'd calculate the total rate of acceptance for this
time period? Can anyone provide their expertise with this?
Is it right to do it like I did or is there a better way?
Using a cast like that is a perfectly valid way to convert a timestamp to a date (I don't understand the reference to the non-existing datediff though - why would adding anything to a timestamp change it)
However, the cast has one drawback: if there is an index on the column "timestamp" it won't be used.
But as you just want a range after a certain date, there is no reason to cast the column to begin with.
The following will achieve the same thing as your query, but can make use of an index on the column "timestamp" in case there is one and using it is considered beneficial by the optimizer.
Select count(distinct check_id)
From Checks
Where "timestamp" > date '2012-07-31' + 1
Note the + 1 which selects the day after, otherwise the query would include rows that are on that date but after midnight.
I removed the unnecessary group by from your query.
If you want to get a count per day, then you will need to include the day in the SELECT list. In that case casting is a good way to do it:
Select "timestamp"::date, count(distinct check_id)
From Checks
Where "timestamp" > date '2012-07-31' + 1
group by "timestamp"::date
I'm trying to run a query against 3 different fields. I want it to return all the accounts that meet the first range, bring back all accounts that meet the second range and same for the third. I tried using and but get dates outside of the range.
select
*
from
Permits
where
created between '1/1/2015' and '1/21/2015'
and updated between '1/1/2015' and '1/21/15'
and noResponseDateSet between '1/1/15' and '1/21/15'
order by
alarmNo
Thanks for helping me
Use ISO standard date formats:
select created, updated, noResponseDateSet
From Permits
where created between '2015-01-01' and '2015-01-21' and
updated between '2015-01-01' and '2015-01-21' and
noResponseDateSet between '2015-01-01' and '2015-01-21' ;
This should fix the problem, unless you have one combination of rather arcane international date settings.
CONVERT can do the dirty parsing work for you. It will accept 1/1/2015 or 01-01-2015 or most other combinations.
select *
From Permits
where created between CONVERT(DATETIME,'1/1/2015') and CONVERT(DATETIME,'1/21/2015')
and updated between CONVERT(DATETIME,'1/1/2015') and CONVERT(DATETIME,'1/21/15')
and noResponseDateSet between CONVERT(DATETIME,'1/1/15') and CONVERT(DATETIME,'1/21/15')
order by alarmNo
I am trying to query my postgresql db to return results where a date is in certain month and year. In other words I would like all the values for a month-year.
The only way i've been able to do it so far is like this:
SELECT user_id
FROM user_logs
WHERE login_date BETWEEN '2014-02-01' AND '2014-02-28'
Problem with this is that I have to calculate the first date and last date before querying the table. Is there a simpler way to do this?
Thanks
With dates (and times) many things become simpler if you use >= start AND < end.
For example:
SELECT
user_id
FROM
user_logs
WHERE
login_date >= '2014-02-01'
AND login_date < '2014-03-01'
In this case you still need to calculate the start date of the month you need, but that should be straight forward in any number of ways.
The end date is also simplified; just add exactly one month. No messing about with 28th, 30th, 31st, etc.
This structure also has the advantage of being able to maintain use of indexes.
Many people may suggest a form such as the following, but they do not use indexes:
WHERE
DATEPART('year', login_date) = 2014
AND DATEPART('month', login_date) = 2
This involves calculating the conditions for every single row in the table (a scan) and not using index to find the range of rows that will match (a range-seek).
From PostreSQL 9.2 Range Types are supported. So you can write this like:
SELECT user_id
FROM user_logs
WHERE '[2014-02-01, 2014-03-01]'::daterange #> login_date
this should be more efficient than the string comparison
Just in case somebody land here... since 8.1 you can simply use:
SELECT user_id
FROM user_logs
WHERE login_date BETWEEN SYMMETRIC '2014-02-01' AND '2014-02-28'
From the docs:
BETWEEN SYMMETRIC is the same as BETWEEN except there is no
requirement that the argument to the left of AND be less than or equal
to the argument on the right. If it is not, those two arguments are
automatically swapped, so that a nonempty range is always implied.
SELECT user_id
FROM user_logs
WHERE login_date BETWEEN '2014-02-01' AND '2014-03-01'
Between keyword works exceptionally for a date. it assumes the time is at 00:00:00 (i.e. midnight) for dates.
Read the documentation.
http://www.postgresql.org/docs/9.1/static/functions-datetime.html
I used a query like that:
WHERE
(
date_trunc('day',table1.date_eval) = '2015-02-09'
)
or
WHERE(date_trunc('day',table1.date_eval) >='2015-02-09'AND date_trunc('day',table1.date_eval) <'2015-02-09')