select all the rows until date difference condition match with grouping - mysql

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.

Related

Average days duration between multiple transactions and latest transaction gap 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

How to count a field per day and then GROUP BY YEARWEEK

If i have a database with 2 columns, date and account and i want to first count account per day and then group by week. How wrong is my code and how to do it?
I edited my code a little bit, i was not thinking right from the beginning. I want the sum to be 9 for week 48.
SELECT date, account,
(SELECT date, COUNT(DISTINCT account)
FROM t1
GROUP BY date
) AS sum
FROM t1
GROUP BY YEARWEEK(date)
You seem to be looking for a simple aggregate query with count(distinct ...):
select yearweek(date) year_week, count(distinct account) cnt_account
from t1
group by yearweek(date)
order by year_week
Note: yearweek() gives you the year and week; this is better than week(), if your data spreads over several years.
EDIT
From the comments, you need two levels of aggregation:
select yearweek(dy) year_week, sum(cnt) cnt_account
from (
select date(t1.date) dy, count(distinct t1.account) cnt
from t1
group by date(t1.date)
) t
group by yearweek(dy)
order by year_week

Average timediff of 2nd and 3rd datetimes for a group

I need to find the average time in days between a customer's second order and third order
I know that I need to use the timestampdiff but am quite at a loss for how to select the second and third dates and need some sort of nest.
SELECT CustomerID,
OrderDate,
diff,
avg(timestampdiff(day, start_date, end_date)) AS average_days
FROM () o3
WHERE date3, date2
ORDER BY CustomerID, OrderDate;
Table
To achieve your desired result, you first need to calculate ROW_NUMBER from your data PARTITION BY CustmerId. Then keep rows only with RowNumber IN (2,3) and then get the DateDiff between two days. The following query will help getting your desired results-
SELECT CustomerID,datediff(MAX(OrderDate),MIN(OrderDate))
FROM
(
SELECT *,
#row_num :=IF(#prev_value = concat_ws('',CsutomerID),#row_num+1,1)AS RowNumber
, #prev_value := concat_ws('',CsutomerID)
FROM your_table A
ORDER BY CustomerID,OrderDate
)B
WHERE B.RowNumber IN (2,3)
GROUP BY CustomerID;

Mysql query to count result by removing time from datetime

I am trying to write one query in which i need to fetch/count records which are registered on same date. But the issue is that in mysql structure created_date field have "datetime" structure.
Let me give you example
If 5 people are registered on 2015-02-25 and 6 people registered on 2015-02-11. It will output as
Sno. Date. count
1) 2015-02-25 5
2) 2015-02-11 6
Here is sample of attached database rows for better understanding
http://i.stack.imgur.com/iPeLl.png
SELECT date(created_at),count(*) FROM myTable GROUP BY date(created_at)
It might be the one that you expected.
SELECT
DATE_FORMAT(created_at,"%Y-%m-%d") AS Date,
COUNT(*) AS count
FROM table_name
GROUP BY DATE_FORMAT(created_at,"%Y-%m-%d")
ORDER BY created_at DESC;
This query will count the registered people in each day. Of course the latest registration will come first.
your query should be like this:
select date(created_at) created_at, count(*) from TABLE
group by date(created_at)
Select between dates
select date(created_at) created_at, count(*) from TABLE
where date(created_at) >= '2015-02-11' and date(created_at) <= '2015-02-25'
group by date(created_at)
With between:
select date(created_at) created_at, count(*) from Mytable
where date(created_at) BETWEEN '2015-01-05' AND '2015-02-25'
group by date(created_at)
Referrence: count()

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).