Join tables with the nearest date - mysql

installment_table:
acc_no
installment_no
due_date
12
1
2022-04-22
12
2
2022-05-22
12
3
2022-06-22
12
4
2022-07-22
12
5
2022-08-22
transaction_table:
acc_no
txn_date
12
2022-04-22
12
2022-05-24
12
2022-06-18
12
2022-07-18
12
2022-08-25
resulting_table:
acc_no
installment_no
due_date
txn_date
days_diff
12
1
2022-04-22
2022-04-22
0
12
2
2022-05-22
2022-05-24
2
12
3
2022-06-22
2022-06-18
-4
12
4
2022-07-22
2022-07-18
-4
12
5
2022-08-22
2022-08-25
3
I want to join the tables based on the account number and the nearest transaction date. Is there a way to do it in MySQL 8.0.37?

You can use a lateral join to evaluate the days difference and select the minimum for each row:
select *
from installment i,
lateral(
select txn_date, DateDiff(txn_date, due_date) days_diff
from transaction t
where t.acc_no = i.acc_no
order by Abs(DateDiff(txn_date, due_date))
limit 1
)t;
See Example fiddle

Related

How to find data for last 20 tuesdays

I want to find data for the last 20 Tuesday.
Date value
2020-03-03 01:12:15 5
2020-02-25 07:12:15 13
2020-02-24 08:12:15 1
2020-02-23 09:12:15 32
2020-02-22 10:12:15 7
2020-02-21 11:12:15 43
2020-02-20 12:12:15 7
2020-02-19 13:12:15 1
2020-02-18 14:12:15 31
2020-02-17 15:12:15 14
and so one
My desired output is
Date value
2020-03-03 01:12:15 5
2020-02-25 07:12:15 13
2020-02-18 14:12:15 31
and so on
Is this what you want?
select t.*
from t
where weekday(date) = 2
order by date desc
limit 3 -- or 20
You can use below query
select t.*
from t
where weekday(date) = 2
order by date desc
limit 20
You could use year and dayofweek
select * from myTable
where year(date) = 2020
and dayofweek(date) = 5

Ranking of the affiliates with most commissions from database

The table "commissions" is of this form:
affiliate referral amount date
3 2 15 2016-08-27
1 22 10 2016-08-29
4 45 5 2016-09-06
1 33 9 2016-09-08
3 17 4 2016-09-11
2 33 10 2016-09-16
1 9 7 2016-09-26
3 17 9 2016-09-26
2 69 10 2016-09-30
1 21 7 2016-10-01
4 55 2 2016-10-06
I need to find out the ranking of the affiliates with most commissions month to month.
I have tried:
SELECT affiliate, SUM(amount) as amount
FROM commissions
GROUP BY affiliate, YEAR(date), MONTH(date)
But unfortunately it is not throwing the desired results.
Please help.

How can I get days between two dates in the same column?

I have table structure like where Loanid is Foreign Key
TranID LOANID TRANSDATE
2 2 2013-05-01
13 2 2013-05-10
14 2 2013-05-15
6 5 2013-05-01
7 5 2013-06-10
8 5 2013-06-14
9 5 2013-07-01
10 5 2013-07-10
i need a query to calculate Days between like below .
TranID LOANID TRANSDATE DAYS_BETWEEN
2 2 2013-05-01 9
13 2 2013-05-10 5
14 2 2013-05-15 0
6 5 2013-05-01 41
7 5 2013-06-10 4
8 5 2013-06-14 17
9 5 2013-07-01 9
10 5 2013-07-10 0
Possibly a self join, using MIN to get the next date.
SELECT t1.tranid,
t1.loanid,
t1.transdate
DATEDIFF(IFNULL(MIN(t2.transdate), t1.transdate), t1.transdate) AS days
FROM some_table t1
LEFT OUTER JOIN some_table t2
ON t1.loanid = t2.loan_id
AND t1.transdate < t2.transdate
GROUP BY t1.tranid,
t1.loanid,
t1.transdate

MYSQL group by month but not on first day of month

My table votes contains votes that have been made by users at different times:
id item_id position user_id created_at
1 2 0 1 11/21/2013 11:27
26 1 1 1 11/21/2013 11:27
27 3 2 1 11/21/2013 11:27
42 2 2 1 12/7/2013 2:20
41 3 1 1 12/7/2013 2:20
40 1 0 1 12/7/2013 2:20
67 2 2 1 12/13/2013 1:13
68 1 1 1 12/13/2013 1:13
69 3 0 1 12/13/2013 1:13
84 2 0 1 12/28/2013 2:29
83 3 2 1 12/28/2013 2:29
82 1 1 1 12/28/2013 2:29
113 3 0 1 1/17/2014 22:08
114 1 1 1 1/17/2014 22:08
115 2 2 1 1/17/2014 22:08
138 2 0 1 1/20/2014 16:49
139 1 1 1 1/20/2014 16:49
140 3 2 1 1/20/2014 16:49
141 1 1 11 1/20/2014 16:51
142 3 2 11 1/20/2014 16:51
143 2 0 11 1/20/2014 16:51
I need to tally the results on a monthly basis but here's the tricky part: the start/end of the month does not necessarily fall on the first day of the month. So if the votes are due on the 10th day of every month, I need a vote that was cast on the 10th to be in a different group from a vote that was cast on the 11th. Using the data above, I want to get three groups:
Group 1: 6 votes (11/21 and 12/7)
Group 2: 6 votes (12/13, 12/28)
Group 3: 9 votes (1/17, 1/20)
I've tried a lot of approaches but to no avail. This is my query right now:
select created_at, ADDDATE(DATE_FORMAT(created_at, '%Y-%m-01'),interval 10 day) as duedate,count("id") from votes where list_id = 2 group by duedate
I am getting group sizes of 3, 9, and 9, not 6, 6 and 9. Any help you can provide would be much appreciated. Thanks.
Your query is close. You just need to subtract 9 days (10 - 1) from the current day to get the month:
select created_at, date_sub(created_at, interval 9 day) as duedate,
count(id)
from votes
where list_id = 2
group by duedate;
date_format() converts a date to a string. There is no need to convert a date value to a character value for this query.
EDIT:
To group by month:
select date_format(date_sub(created_at, interval 9 day), '%Y-%m') as YYYYMM,
count(id)
from votes
where list_id = 2
group by YYYYMM;

mySQL AVG a field with a range of dates on the same table

I have a table
date d_id r_id p_id q_sold onhand
2012-10-10 5 1 3025 3 10
2012-10-10 5 1 3022 12 20
2012-10-10 5 1 3023 15 33
2012-10-11 5 1 3025 3 10
2012-10-11 5 1 3022 12 20
2012-10-11 5 1 3023 15 33
2012-10-12 5 1 3025 3 10
2012-10-12 5 1 3022 12 20
2012-10-12 5 1 3023 15 33
2012-10-13 5 1 3025 3 10
2012-10-13 5 1 3022 12 20
2012-10-13 5 1 3023 15 33
2012-10-14 5 1 3025 3 10
2012-10-14 5 1 3022 12 10
2012-10-14 5 1 3023 15 33
2012-10-15 5 1 3025 3 5
2012-10-15 5 1 3022 12 5
2012-10-15 5 1 3023 15 33
I would like to get the result of the q_sold divided by average of the onhand over a 5 day period, while displaying the other data for a specific date like the 2012-10-15.
I create a query
set #stdate = '2012-10-10';
set #endate = '2012-10-15';
SELECT date, d_id,r_id,p_id,q_sold,onhand,qty_sold/AVG(qty_onhand)
FROM stp_vwsales_info_tots
WHERE date BETWEEN #stdate and #endate and d_id=5
GROUP BY d_id,r_id,p_id
But the result being showed is incorrect, it displays the data for the 2012-10-10 instead of 2010-10-15
date d_id r_id p_id q_sold onhand avg
2012-10-10 5 1 3022 12 20 0.7579
2012-10-10 5 1 3023 15 33 0.4545
2012-10-10 5 1 3025 3 10 0.3273
Can anyone help?
Use your #stdate and #endate as DATE(#stdate/#endate) or DATE_FORMAT(#stdate/#endate,'%Y-%m-%d') otherwise you have to convert #stdate/#endate from string to date through MySQL
i think what your looking for is something called a simple moving average.
to calculate this you'll need to use an inline subquery - so performance won't be the best.
assuming you want to calculate the average over the previous 5 day period, try something like this:
SELECT
date, d_id, r_id, p_id, q_sold, onhand,
( SELECT q_sold/AVG(t2.onhand)
FROM stp_vwsales_info_tots AS t2
WHERE p_id=t1.p_id AND DATEDIFF(t1.date, t2.date) BETWEEN 0 AND 4
) AS 'moving_avg'
FROM stp_vwsales_info_tots AS t1
GROUP BY t1.p_id,t1.date
order by t1.date;