Cumulative count on date data from datetime format - sql

I have a table looks like:
ID entry_time
abc123 2020-05-29 10:29:18.000
def456 2020-05-30 13:12:43.000
...
I want to do cumulative count by date, so I did:
select entry_time, count (*) OVER (ORDER BY entry_time) as TOTAL_NUM from my_table;
It is okay, but it will count based on datetime format. I would like to count only on date (i.e. by day, don't care about time).
How would I do that?
Many thanks,

You can try by converting entry time to date.
select
convert(date, entry_time) as entry_time,
count (*) OVER (ORDER BY convert(date, entry_time)) as total_num
from my_table;

If you want one record per day, you can use aggregation and window functions:
select
date(entry_time) entry_day,
sum(count(*)) over(order by date(entry_time)) total_num
from mytable
group by date(entry_time)
order by entry_day
This assumes that your database supports the date(), that converts a datetime to a date (as in MySQL for example). If it does not, it sure has an alternative way to do this.

You can use convert or cast entry_time to Date
select entry_time, count (*) OVER (ORDER BY Convert(date,entry_time)) as TOTAL_NUM from my_table;
OR
select entry_time, count (*) OVER (ORDER BY Cast(entry_timeas as date)) as TOTAL_NUM from my_table;

Related

Find the average lowest item in a collection grouped by date in SQL

My SQL isn't the best - I can get this working in C# but it seems more efficient to get it in my data layer - I've got a table Prices:
ID
Price
DateTime
Each row is exactly 1 hour from the next, so I have a snapshot of a price every hour.
I'm trying to work out which hour in a day over the entire dataset has the lowest price (on average).
So ideally I'm after a list of each hour in the day ranked by how cheap on average that hour is over the entire dataset - so a maximum of 24 rows (one for each hour in the day).
Any help would be greatly appreciated!
Thanks :D
Which database are you on?
Different DBs have different ways to extract date from a timestamp column.
Postgres has date(timestamp), In Oracle, you can use trunc(timestamp). Or most DBs have to_char/to_date. So you can try that.
Once you have extracted the date, you can try something like this -
select ID,
Price,
DateTime,
trunc(DateTime) as day,
rank() over (partition by trunc(DateTime) order by Price asc) as least_for_day
from Prices
Now you can use the "least_for_day" ranked column and select by day.
Again, depending on the DB, you can either directly qualify on the ranked column in the same SQL or use the above as a sub-query and filter for the rank.
You can use a query like below
select
hour,
avg(daily_rank) avg_rank
from
(
select *, hour= format((datetime as datetime),'HH'), daily_rank= dense_rank() over (partition by cast(datetime as date) order by price asc)
) t
group by hour
Thank you very much to #Many Manjunath and #DhruvJoshi. Final solution below;
WITH prices AS
(
SELECT
[Price],
[DateTime],
CAST([DateTime] AS TIME) 'Time',
CAST([DateTime] as date) 'Date',
rank() over (partition by cast([DateTime] as date) order by [Price] asc) as least_for_day
FROM [dbo].[Prices]
)
SELECT [Time], count(*) 'Qty Cheapest' FROM prices
WHERE least_for_day = 1
GROUP BY [Time]
ORDER BY 2 DESC
That returns 24 rows:

Oracle SQL - count by day - not a GROUP BY expression

I have data which looks like this:
TIME ID
29/11/20 13:45:33,810000000 1234
06/01/21 13:45:33,810000000 5678
06/01/21 14:05:33,727000000 5678
That means, I have a column TIME and ID. What I want to do is to count all the entries by day and all the distinct IDs per day.
As result I would like to get this:
DAY COUNT(*) distinctID
29/11/20 1 1
06/01/21 2 1
I did this:
select trunc(to_char(TIME, ‘HH’),'DD/MM/YY'),
COUNT(*), count(distinct ID) as distinctID from CDRHEADER
where TIME>= date '2021-03-01'
group by trunc(TIME,'DD/MM/YY')
order by trunc(TIME,'DD/MM/YY');
As error I get: not a GROUP BY Expression.
Furthermore, I am also not sure about the date operations I executed and if they are correct.
NOTE: I would like to use the date entries as date values and not compare strings or something like this.
How can I get what I expect?
Hmmm . . . I think you want:
select trunc(time) as the_date,
count(*), count(distinct ID) as distinctID
from CDRHEADER
where time >= date '2021-03-01'
group by trunc(time)
order by trunc(time);
I'm not sure why you are using to_char() or 'HH'. If you really want to output the time as 'DD/MM/YYYY', then:
select to_char(trunc(time), 'DD/MM/YYYY') as the_date,
count(*), count(distinct ID) as distinctID
from CDRHEADER
where time >= date '2021-03-01'
group by trunc(time)
order by trunc(time);

The Maximum value of two columns with group by

I have a table that contains the followings data :
TRIP TRIP_DATE TRIP_TIME
A 2018-08-08 11:00
A 2018-08-09 11:00
A 2018-08-08 23:00
A 2018-08-20 11:00
A 2018-08-20 14:00
I want the select statement to retrieve the Number of trips, Count , the latest date and time.
Basically the output should be like this:
TRIPS MAX(TRIP_DATE) TRIP_TIME
5 2018-08-20 14:00
This is tricky. I think I would do:
select cnt, date, time
from (select t.*,
row_number() over (partition by trip order by date desc, time desc) as seqnum
count(*) over (partition by trip) as cnt
from t
) t
where seqnum = 1;
You can use the following using GROUP BY:
SELECT TRIP, COUNT(TRIP) AS cnt, MAX(CONCAT(TRIP_DATE, ' ', TRIP_TIME)) AS maxDateTime
FROM table_name
GROUP BY TRIP
To combine the DATE and TIME value you can use one of the following:
using CONCAT_WS: CONCAT_WS(' ', TRIP_DATE, TRIP_TIME)
using CONCAT: CONCAT(TRIP_DATE, ' ', TRIP_TIME)
You can use the above query as sub-query to get the DATE and TIME as seperate values:
SELECT TRIP, cnt, DATE(maxDateTime), TIME_FORMAT(TIME(maxDateTime), '%H:%i') FROM (
SELECT TRIP, COUNT(TRIP) AS cnt, MAX(CONCAT(TRIP_DATE, ' ', TRIP_TIME)) AS maxDateTime
FROM table_name
GROUP BY TRIP
)t;
Note: I recommend to split the DATE and TIME values on the application side. I would also store the DATE and TIME value in one column as DATETIME instead of separate columns.
demos: https://www.db-fiddle.com/f/xcMdmivjJa29rDhHxkUmuJ/2
You can use row_number() function :
select t.*
from (select *, row_number() over (partition by trip order by date desc, time desc) seq
from table t
) t
where seq = 1;
I would go with this (assuming you wanted the MAX Trip_Time as well, its a little difficult to tell from your example):
SELECT COUNT(TRIP) AS Trips,
MAX(TRIP_DATE) AS MAX(TRIP_DATE),
MAX(TRIP_TIME) AS TRIP_TIME
FROM myTable
GROUP BY TRIP
You have option of using analytic function as will as group function here.
All will do the job . Looking at final output I believe max function with group by is more suitable.
There is no hard and fast rule but personally I prefer grouping when final outcome need to be suppressed.

SQL Count of date values that dont match hour and day in select statement

I have a problem unique to a business process. My user needs to know how many dates, counted, are before a specific end time that do not match on the hour or the day.
Here is an example.
AAA, 2016-03-15 16:00:28.967, 2016-03-15 16:02:58.487, 2016-03-17 14:01:24.243
In the example above id AAA has 3 entries. I need to count only the ones that don't have a matching hour and day. So the actual count should come out to be 2.
I have to do this all in SQL and can't use a CTE. It needs to be either a sub select or some type of join.
Something like this.
SELECT id, date, (
SELECT COUNT(*)
FROM x
WHERE day!=day
AND hour!=hour AND date < z
) AS DateCount
Results would be AAA, 2
I am thinking some type of recursive comparison but I am not sure how to accomplish this without a CTE.
In SQL Server you can try something like this:
SELECT id, CONVERT(VARCHAR(13), [date], 120) AS [Date], COUNT(*) AS DateCount
FROM YourTable
WHERE [date] < #ENDDATE
GROUP BY id, CONVERT(VARCHAR(13), [date], 120)
SELECT a AS current_a, COUNT(*) AS b,day AS day, hour as hour,
(SELECT COUNT(*)
FROM t
WHERE day != day
AND hour != hour
AND date < z ) as datecount
FROM t GROUP BY a ORDER by b DESC

Compute count and running total for date field in SQL

Here is my dilemma. I have a field in the SQL database, called booking_date. The date is in a format like this
2014-10-13 12:05:58.533
I would like to be able to compute a count of bookings for each date (not date time) as well as a running total.
So my report would look something like so
My SQL code is like so
SELECT
dbo.book.create_time,
replace(convert(nvarchar, dbo.book.create_time, 106),' ', '/') as bookingcreation,
count(*) as Book_Count
FROM
....tables here
However, my count calculation is counting the date based of this type of date format > 2014-10-13 12:05:58.533 which is not computing correctly.
So instead, I'm getting this:
Also, I am not sure how to compute the running total. But I first need to get the count correctly.
Any help is greatly appreciated.
You seem to be using SQL Server. To get the count by day:
SELECT cast(dbo.book.create_time as date) as create_date
count(*) as Book_Count
FROM ...tables here
GROUP BY cast(dbo.book.create_time as date)
ORDER BY create_date;
You can get the cumulative sum in SQL Server 2012+ using the cumulative sum function:
SELECT cast(dbo.book.create_time as date) as create_date
count(*) as Book_Count,
sum(count(*)) over (order by cast(dbo.book.create_time as date) ) as Running_Count
FROM ...tables here
GROUP BY cast(dbo.book.create_time as date)
ORDER BY create_date;
In earlier versions, you can do something similar with a correlated subquery or cross apply.
EDIT:
In SQL Server 2008, you can do:
WITH t as (
SELECT cast(dbo.book.create_time as date) as create_date
count(*) as Book_Count
FROM ...tables here
GROUP BY cast(dbo.book.create_time as date)
)
SELECT t.create_date, t.Book_Count,
(SELECT SUM(Book_Count)
FROM t t2
WHERE t2.create_date <= t.create_date
) as Running_Count
FROM t
ORDER BY create_date;
Try to use trunc(book.create_time) in your query instead of the conversion you're doing