Average days duration between multiple transactions and latest transaction gap mysql - mysql

I have the transaction table with the following columns :
TRANSACTION_ID, USER_ID, MERCHANT_NAME, TRANSACTION_DATE, AMOUNT
-)Query to calculate time difference (in days) between current and previous order of
each customer
-)the avg time difference between two orders for every
customer.
Note : Exclude users with single transactions
I tried the following code to get the 1st part of the query but it looks too messy
with t1 as
(Select USER_ID,TRANSACTION_DATE,Dense_rank() over(partition by USER_ID order by TRANSACTION_DATE desc) as r1
from CDM_Bill_Details
order by USER_ID, TRANSACTION_DATE desc)
Select t11.USER_ID, datediff(t11.TRANSACTION_DATE,t111.TRANSACTION_DATE) from t1 as t11,t1 as t111
where (t11.r1=1 and t111.r1=2) and (t11.USER_ID=t111.USER_ID)

Please try this:
with t2 as (select *,
lag(t1.TRANSACTION_DATE, 1) OVER (PARTITION BY USER_ID ORDER BY TRANSACTION_DATE) AS previous_date,
datediff(t1.TRANSACTION_DATE, lag(t1.TRANSACTION_DATE, 1) OVER (PARTITION BY USER_ID ORDER BY TRANSACTION_DATE)) AS diff_prev_curr
from CDM_Bill_Details t1)
select *,
avg(diff_prev_curr) OVER (PARTITION BY USER_ID) AS avg_days_diff
from t2
where previous_date is not null

Related

SQL Query to get most recent date of transaction

New to SQL. Can someone please tell me if my SQL query is correct? I am trying to find out how much each unique customer spent on their most recent transaction.
Table Name: Expenditure
Columns:
1. created_time
2. customer_id
3. spend
SELECT
distinct(customer_id), sum(spend)
FROM
Expenditure
WHERE
created_time =
(SELECT MAX(created_time))
FROM
Expenditure
GROUP BY
distinct(customer_id)
If you are using MySQL 8+, then I prefer to use window functions here:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY created_time DESC) rn
FROM Expenditure
)
SELECT customer_id, created_time, spend
FROM cte
WHERE rn = 1;
To correct the approach you were trying to use, you can correlate the subquery to the outer query by customer:
SELECT customer_id, created_time, spend
FROM expenditure e1
WHERE created_time = (SELECT MAX(e2.created_time)
FROM Expenditure
WHERE e2.customer_id = e1.customer_id);

how to retrieve the difference between the two given dates in SQL

How to find the Longest Booking ID for the given two dates and Costliest Booking ID for the given cost.
Here we have the 13 days difference so we are getting the longest booking id as 1.
what are the approach to archive this using sql query.
this will work:
(SELECT 'Total Booking Count' AS Label, COUNT(*) AS Value FROM bookings)
UNION ALL
(SELECT 'Longest Booking Id', booking_id FROM bookings ORDER BY DATEDIFF(enddate, startdate) DESC LIMIT 1)
UNION ALL
(SELECT 'Costliest Booking Id', booking_id FROM bookings ORDER BY (tariff*DATEDIFF(enddate, startdate)) DESC LIMIT 1)
with data
as (select *
,row_number() over(order by datediff(dd,end_date,start_date) desc) as rnk_time
,row_number() over(order by tarrif desc) as rnk_cost
,count(*) over(partition by 1) as tot_cnt
from your_table
)
select 'Total Booking count',tot_cnt
from data
where rnk_time=1
union all
select 'Longest Booking id',booking_id
from data
where rnk_time=1
union all
select 'Costliest Booking id',booking_id
from data
where rnk_cost=1

To find the maximum number of order count that occur in any 1 hour of the day from the database?

I have a food selling website in which there is order table which record the order of every user.It column for user id ,user name,orderid ,timestamp of order.I want to know the maximum number of order that has been made in any one hour span through out the day.Give me any formula for this,or any algorithm or any sql queries for these.
SQL server:
with CTE as
(
select cast(t1.timestamp as date) as o_date, datepart(hh, t1.timestamp) as o_hour, count(*) as orders
from MyTable t1
group by cast(t1.timestamp as date), datepart(hh, t1.timestamp)
)
select o_date, o_hour, orders
from CTE
where orders = (select max(orders) from CTE)
Oracle
with CTE as
(
select to_char(t1.timestamp, 'YYYYMMDD') as o_date, to_char(t1.timestamp, 'HH24') as o_hour, count(*)
from MyTable t1
group by to_char(t1.timestamp, 'YYYYMMDD'), to_char(t1.timestamp, 'HH24')
)
select o_date, o_hour, orders
from CTE
where orders = (select max(orders) from CTE)
You can get count by day and hour like this
For SQL
SELECT TOP 1
COUNT(*)
FROM myTable
GROUP BY DATEPART(day, [column_date]), DATEPART(hour, [column_date])
ORDER BY COUNT(*) DESC;
For MySQL
SELECT
COUNT(*)
FROM myTable
GROUP BY HOUR(column_date), DAY(column_date)
ORDER BY COUNT(*) DESC
LIMIT 1;

MySQL - How to select rows with the min(timestamp) per hour of a given date

I have a table of production readings and need to get a result set containing a row for the min(timestamp) for EACH hour.
The column layout is quite simple:
ID,TIMESTAMP,SOURCE_ID,SOURCE_VALUE
The data sample would look like:
123,'2013-03-01 06:05:24',PMPROD,12345678.99
124,'2013-03-01 06:15:17',PMPROD,88888888.99
125,'2013-03-01 06:25:24',PMPROD,33333333.33
126,'2013-03-01 06:38:14',PMPROD,44444444.44
127,'2013-03-01 07:12:04',PMPROD,55555555.55
128,'2013-03-01 10:38:14',PMPROD,44444444.44
129,'2013-03-01 10:56:14',PMPROD,22222222.22
130,'2013-03-01 15:28:02',PMPROD,66666666.66
Records are added to this table throughout the day and the source_value is already calculated, so no sum is needed.
I can't figure out how to get a row for the min(timestamp) for each hour of the current_date.
select *
from source_readings
use index(ID_And_Time)
where source_id = 'PMPROD'
and date(timestamp)=CURRENT_DATE
and timestamp =
( select min(timestamp)
from source_readings use index(ID_And_Time)
where source_id = 'PMPROD'
)
The above code, of course, gives me one record. I need one record for the min(hour(timestamp)) of the current_date.
My result set should contain the rows for IDs: 123,127,128,130. I've played with it for hours. Who can be my hero? :)
Try below:
SELECT * FROM source_readings
JOIN
(
SELECT ID, DATE_FORMAT(timestamp, '%Y-%m-%d %H') as current_hour,MIN(timestamp)
FROM source_readings
WHERE source_id = 'PMPROD'
GROUP BY current_hour
) As reading_min
ON source_readings.ID = reading_min.ID
SELECT a.*
FROM Table1 a
INNER JOIN
(
SELECT DATE(TIMESTAMP) date,
HOUR(TIMESTAMP) hour,
MIN(TIMESTAMP) min_date
FROM Table1
GROUP BY DATE(TIMESTAMP), HOUR(TIMESTAMP)
) b ON DATE(a.TIMESTAMP) = b.date AND
HOUR(a.TIMESTAMP) = b.hour AND
a.timestamp = b.min_date
SQLFiddle Demo
With window function:
WITH ranked (
SELECT *, ROW_NUMBER() OVER(PARTITION BY HOUR(timestamp) ORDER BY timestamp) rn
FROM source_readings -- original table
WHERE date(timestamp)=CURRENT_DATE AND source_id = 'PMPROD' -- your custom filter
)
SELECT * -- this will contain `rn` column. you can select only necessary columns
FROM ranked
WHERE rn=1
I haven't tested it, but the basic idea is:
1) ROW_NUMBER() OVER(PARTITION BY HOUR(timestamp) ORDER BY timestamp)
This will give each row a number, starting from 1 for each hour, increasing by timestamp. The result might look like:
|rest of columns |rn
123,'2013-03-01 06:05:24',PMPROD,12345678.99,1
124,'2013-03-01 06:15:17',PMPROD,88888888.99,2
125,'2013-03-01 06:25:24',PMPROD,33333333.33,3
126,'2013-03-01 06:38:14',PMPROD,44444444.44,4
127,'2013-03-01 07:12:04',PMPROD,55555555.55,1
128,'2013-03-01 10:38:14',PMPROD,44444444.44,1
129,'2013-03-01 10:56:14',PMPROD,22222222.22,2
130,'2013-03-01 15:28:02',PMPROD,66666666.66,1
2) Then on the main query we select only rows with rn=1, in other words, rows that has lowest timestamp in each hourly partition (1st row after sorted by timestamp in each hour).

select all the rows until date difference condition match with grouping

with reference to this question
select all the rows until date diff is 4 from bottom
Solution works great but how to group by customer_id and for each customer_id group by 4 day diff, 8 day diff
http://sqlfiddle.com/#!2/93d75/3
You just need to keep track of the latest customer_id and perform the 'okay' logic on that too:
SELECT amount, customer_id, updated_at, date_diff
FROM (
SELECT *,
#b:=NOT #c<=>customer_id
OR (#b AND DATEDIFF(#t,updated_at)<=date_diff) AS okay,
#c:=customer_id,
#t:=updated_at
FROM my_table, (SELECT 4 AS date_diff) init
ORDER BY customer_id, updated_at DESC
) t
WHERE okay
ORDER BY customer_id, updated_at, id
See it on sqlfiddle.