It looks like Chrome does not display the tables but it works fine on Edge
For some reason, I get a duplicate when end_at has the same value as time.
The query used:
SELECT DISTINCT
TIME(hour, 0, 0) AS time,
date,
start_at,
end_at,
total
FROM a, UNNEST(GENERATE_ARRAY(0, 23)) hour
WHERE hour BETWEEN EXTRACT(hour FROM TIME(start_at)) AND EXTRACT(hour FROM TIME(end_at))
GROUP BY 1,2,3,4,5
Any help would be greatly appreciated :)
Duplicates seems to be occurred because BETWEEN operator is inclusive.
In your case, 3rd row with '22:53:37' in start_at and '23:00:00' in end_at will be expanded into two rows by cross-joining with hour with key 22 and 23, and will make duplication.
Consider below instead of using BETWEEN operator
WHERE TIME(hour, 0, 0) >= TIME_TRUNC(start_at, HOUR) AND TIME(hour, 0, 0) < end_at
Note: assuming start_at column and end_at column are TIME data type.
Above condition generates below output:
Related
Since the data is refreshing several times per day, I would like to have only finished days in my query results, thus the last day should be yesterday.
At the moment I'm running this query and it's not catching the data for the last day, but only for the last 24 hours:
AND to_iso8601(date_trunc('DAY', date_add('DAY', 0, NOW()))) >= event_time
I'm trying with these queries, but it's not working:
AND to_iso8601(date_trunc('DAY', date_add('DAY', -1, CURRENT_DATE)) >= event_time
AND to_iso8601(date_trunc('DAY', date_add('DAY', -1, CURRENT_DATE())) >= event_time
With this query, I'm getting the data till today-24h, 2022-09-08 10:50CET (it's 10:50h at the moment in my timezone) :
SELECT
mc_type,
cast(from_iso8601_timestamp(event_time) AS date) AS event_time,
query_cost
FROM
table
WHERE
to_iso8601(date_trunc('DAY', date_add('DAY', 0, NOW()))) >= event_time
But I would like to get the data for the whole day yesterday, so till 2022-09-08 23:59CET
Any ideas on how should I change the query?
I suggest to perform dates comparison instead of varchar/string one. I.e.:
WHERE
date_trunc('DAY', now()) > from_iso8601_timestamp(event_time)
I am running the below query to get data recorded in the past 24 hours. I need the same data recorded starting midnight (DATE > 12:00 AM) and also data recorded starting beginning of the month. Not sure if using between will work or if there is better option. Any suggestions.
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CNLD'
AND
TRUNC(TO_DATE('1970-01-01','YYYY-MM-DD') + OPEN_DATE/86400) = trunc(sysdate)
Output (Just need Count). OPEN_DATE Data Type is NUMBER. the output below displays count in last 24 hours. I need the count beginning midnight and another count starting beginning of the month.
The query you've shown will get the count of rows where OPEN_DATE is an 'epoch date' number representing time after midnight this morning*. The condition:
TRUNC(TO_DATE('1970-01-01','YYYY-MM-DD') + OPEN_DATE/86400) = trunc(sysdate)
requires every OPEN_DATE value in your table (or at least all those for CNLD rows) to be converted from a number to an actual date, which is going to be doing a lot more work than necessary, and would stop a standard index against that column being used. It could be rewritten as:
OPEN_DATE >= (trunc(sysdate) - date '1970-01-01') * 86400
which converts midnight this morning to its epoch equivalent, once, and compares all the numbers against that value; using an index if there is one and the optimiser thinks it's appropriate.
To get everything since the start of the month you could just change the default behaviour of trunc(), which is to truncate to the 'DD' element, to truncate to the start of the month instead:
OPEN_DATE >= (trunc(sysdate, 'MM') - date '1970-01-01') * 86400
And the the last 24 hours, subtract a day from the current time instead of truncating it:
OPEN_DATE >= ((sysdate - 1) - date '1970-01-01') * 86400
db<>fiddle with some made-up data to get 72 back for today, more for the last 24 hours, and more still for the whole month.
Based on your current query I'm assuming there won't be any future-dated values, so you don't need to worry about an upper bound for any of these.
*Ignoring leap seconds...
It sounds like you have a column that is of data type TIMESTAMP and you only want to select rows where that TIMESTAMP indicates that it is today's date? And as a related problem, you want to find those that are the current month, based on some system values like CURRENT TIMESTAMP and CURRENT DATE? If so, let's call your column TRANSACTION_TIMESTAMP instead of (reserved word) DATE. Your first query could be:
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CLND'
AND
DATE(TRANSACTION_TIMESTAMP)=CURRENT DATE
The second example of finding all for the current month up to today's date could be:
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CLND'
AND
YEAR(DATE(TRANSACTION_TIMESTAMP)=YEAR(CURRENT DATE) AND
MONTH(DATE(TRANSACTION_TIMESTAMP)=MONTH(CURRENT DATE) AND
DAY(DATE(TRANSACTION_TIMESTAMP)<=DAY(CURRENT DATE)
Its an interesting question I came across with.
I have an table
create table phonebook(
customer_id (varchar 30)
call_start_day (date)
call_end_day (date)
call_start_time (varchar 30)
call_end_time (varchar 30)
called_number (integer)
customer_call_location_city (varchar 30)
customer_call_location_state (varchar 30)
customer_call_location_zip (integer)
called_number_city (varchar 30)
called_number_state (varchar 30)
)
I need to to find top n customer based on average monthly call_duration in last 12 months. (consider only complete months only e.g., if current date is 2021-03-07, last 12 months: 2020-03-01 – 2021-02-28. Monthly call duration = sum (call duration) where call duration = time difference of call_end_day+ call_end_time and call_start_day+call_start_time)
Solution- I thought to find out the time and then their average. Any Suggestions?
In SQL Server, start by working out expressions that give
the first date you want to consider.
the day after the last date you want to consider.
EOMONTH() is good for this.
SELECT DATEADD(DAY, 1, EOMONTH(GETDATE(),-1)) day_after_last,
DATEADD(DAY, 1, EOMONTH(GETDATE(), -13)) first
Next, figure out how to get the call duration. You haven't told us how you represent your call_start_time and call_end_time, so we can't help you with that detail. So I'll represent the duration calculation as a stored function. It's up to you to figure out how to get the duration. Probably duration in seconds is the best way to go for call detail records.
Pro tip Never, never use varchars or chars to represent DATE, TIME, or DATETIME data. They always lead to confusion and grief.
Here's the way to go.
SELECT TOP (5) customer_id,
AVG(dbo.duration(call_start_day, call_start_time,
call_end_day, call_end_time)) average
FROM phonebook
WHERE call_start_day >= DATEADD(DAY, 1, EOMONTH(GETDATE(), -13))
AND call_start_day < DATEADD(DAY, 1, EOMONTH(GETDATE(),-1))
GROUP BY customer_id
ORDER BY 2 DESC;
The WHERE clause pulls in only the records with dates you care about.
The ORDER BY 2 DESC clause means order by the result set's second column, highest to lowest. The TOP (5) clause means display the first five rows of the ordered result set.
Edit
If your time columns look like 08:47:13 then you can compute the durations with DATEDIFF(). It looks like this
DATEDIFF(
second,
CAST(call_start_day AS DATETIME) + CAST(call_start_time AS DATETIME),
CAST(call_end_day AS DATETIME) + CAST(call_end_time AS DATETIME))
So your query looks like this:
SELECT TOP (5) customer_id,
AVG(
DATEDIFF(
second,
CAST(call_start_day AS DATETIME) +
CAST(call_start_time AS DATETIME),
CAST(call_end_day AS DATETIME) +
CAST(call_end_time AS DATETIME))) average
FROM phonebook
WHERE call_start_day >= DATEADD(DAY, 1, EOMONTH(GETDATE(), -13))
AND call_start_day < DATEADD(DAY, 1, EOMONTH(GETDATE(),-1))
GROUP BY customer_id
ORDER BY 2 DESC;
I need to group data in intervals of 15 (or X) minutes in sql.
For example, i have the next scenario.
The result that i expect to obtain is
I tried using Lag function but i dont get what i want, because it add interval to each row and continues grouping.
Thanks in advance and apologies for my bad english.
If you want the intervals to be calendar based -- i.e. four per hour starting at 0, 15, 30, and 45 minutes, then you can use:
select id, min(begin_date), max(begin_date)
from t
group by id, convert(date, begin_date),
datepart(hour, begin_date), datepart(minute, begin_date) / 15;
Note that begin date and end date have the same value, so I just used begin_date in this answer.
I am confused by the nature of logical operators upon datetime data in sql.
In my database's table RecordDateTime is saved like:
2014-04-09 15:28:32.000
I am retrieving on basis of this query:
select
*
from [GPSDB].[dbo].[Coordinates]
where IMEI= '354400055967495'
and RecordedDateTime >= '2014-04-09 15:28:32.000'
and RecordedDateTime <= '2014-04-09 15:39:20.000'
Now it returns 4 rows which falls between these both dates range or equal as expected but confusion starts from here when i remove Seconds part from first date then still it works and returns same result set i.e.
select
*
from [GPSDB].[dbo].[Coordinates]
where IMEI = '354400055967495'
and RecordedDateTime >= '2014-04-09 15:28'
and RecordedDateTime <= '2014-04-09 15:39:20.000'
but if i remove seconds part from 2nd date then it returns only one row with matching time of first date being provided. Weird ? :/
Help Please.
the datetime data 2014-04-09 15:28:32.000 have two part date part 2014-04-09 and time part 15:28:32.000.
So when you say
RecordedDateTime >= '2014-04-09 15:28:32.000' and RecordedDateTime <= '2014-04-09 15:39:20.000'
It will consider the time part as well and since there is 11 minutes gap between; it will fetch you all those record which falls in that range.
But when you say below, it will consider only the date part for comparison and there is only 1 day and hence it will fetch the first record of that date 2014-04-09
RecordedDateTime >= '2014-04-09'
and RecordedDateTime <= '2014-04-09'