Sum the duplicate values order by date from sql table [duplicate] - mysql

This question already has an answer here:
How to sum the duplicate values from mysql table
(1 answer)
Closed 4 years ago.
I have a MySQL table with rows containing duplicate values of Ref_Nr column. So i want to sum the values of Points with respect Ref_Nr, to u_id and r_date columns.
id u_id r_date Points Ref_Nr
1 1 2018-04-11 1 3
2 1 2018-04-11 2 3
3 2 2018-04-11 3 4
4 2 2018-04-11 4 4
5 3 2018-04-11 6 2
6 3 2018-04-11 6 2
7 1 2018-04-10 3 3
8 1 2018-04-10 5 3
9 1 2018-04-10 2 4
10 1 2018-04-10 2 4
11 2 2018-04-10 3 3
12 2 2018-04-10 5 3
13 3 2018-04-10 2 4
14 3 2018-04-10 2 4
Here is the my sql query what i tried, but i am not getting proper output
SELECT u_id, Ref_Nr ,r_date, SUM(Points) AS Points
FROM my_table ORDER BY r_date, Ref_nr,u_id;
Here is the expected output, please help me to solve this problem
u_id r_date Points Ref_Nr
1 2018-04-11 3 3
2 2018-04-11 7 4
3 2018-04-11 12 2
1 2018-04-10 8 3
1 2018-04-10 4 4
2 2018-04-10 8 3
3 2018-04-10 4 4

You need to group tha data. You can't mix normal column selects with aggregate functions like sum()
SELECT r_date, Ref_nr, u_id,
SUM(Points) AS PointSum
FROM my_table
GROUP BY r_date, Ref_nr, u_id
ORDER BY r_date, Ref_nr, u_id;

Related

calculating the average of marks from the beginning to this record

i have a table named test with the below structure like this
id mark join_id
1 5 1
2 4 1
3 9 1
4 5 2
5 7 2
6 12 2
i want to write a query that can get me the average of the marks from the beginning record to this record with the desired result as below
id mark join_id avg_of_previous_marks
1 5 1 5
2 4 1 4.5
3 9 1 6
4 5 2 5.75
5 7 2 6
6 12 2 7
i wrote this query but it doesn't seem to work correctly
SELECT test.id, test.mark, test.join_id, test_avg.avg_of_previous_marks FROM test
LEFT JOIN (SELECT id, join_id, AVG(mark) as avg_of_previous_marks FROM test GROUP BY
join_id) test_avg
ON test_avg.join_id = test.join_id AND test_avg.id <= test.id
and it gives this resault
id mark join_id avg_of_previous_marks
1 5 1 6
2 4 1 6
3 9 1 6
4 5 2 8
5 7 2 8
6 12 2 8
Its a simple running total that you need.
select id,mark,join_id, avg(mark) over (order by id) avg_of_previous_marks from test_avg ;
fiddle here

MYSQL I am trying to return a value where I need to compare one value against the minimum value for the same field when grouped against another field

Basically I am trying to calculate shots received in golf for various four balls, here is my data:-
DatePlayed PlayerID HCap Groups Hole01 Hole02 Hole03 Shots
----------------------------------------------------------------------
2018-11-10 001 15 2 7 3 6
2018-11-10 004 20 1 7 4 6
2018-11-10 025 20 2 7 4 5
2018-11-10 047 17 1 8 3 6
2018-11-10 048 20 2 8 4 6
2018-11-10 056 17 1 6 3 5
2018-11-10 087 18 1 7 3 5
I want to retrieve the above lines with an additional column which is to be calculated depending on the value in the group column, which is the players (Handicap - (the lowest handicap in the group)) x .75
I can achieve it in a group by but need to aggregate everything, is there a way I can return the value as above?, here is query that returns the value:
SELECT
PlayerID,
MIN(Handicap),
MIN(Hole01) AS Hole01,
MIN(Hole02) AS Hole02,
MIN(Hole03) AS Hole03,
MIN(CourseID) AS CourseID,
Groups,
ROUND(
MIN((Handicap -
(SELECT MIN(Handicap) FROM Results AS t
WHERE DatePlayed='2018-11-10 00:00:00' AND t.Groups=Results.Groups)) *.75))
AS Shots
FROM
Results
WHERE
Results.DatePlayed='2018=11=10 00:00:00'
GROUP BY
DatePlayed, Groups, PlayerID
.
PlayerID MIN(Handicap)Hole01 Hole02 Hole03 CourseID Groups Shots
-----------------------------------------------------------------
4 20 7 4 6 1 1 2
47 17 8 3 6 1 1 0
56 17 6 3 5 1 1 0
87 18 7 3 5 1 1 1
1 15 7 3 6 1 2 0
25 20 7 4 5 1 2 4
48 20 8 4 6 1 2 4
Sorry about any formatting really couldn't see how to get my table in here, any help will be much appreciated, I am using the latest mysql from ubuntu 18.04
Not an answer; too long for a comment...
First off, I happily know nothing about golf, so what follows might not be optimal, but it must, at least, be a step in the right direction...
A normalized schema might look something like this...
rounds
round_id DatePlayed PlayerID HCap Groups
1 2018-11-10 1 15 2
2 2018-11-10 4 20 1
round_detail
round_id hole shots
1 1 7
1 2 3
1 3 6
2 1 7
2 2 4
2 3 6
Hi Guys I have found the solution, basically I need to drop the MIN immediately after the ROUND of the equation and therefore it does not need a Group By.
SELECT
PlayerID,
Handicap,
Hole01,
Hole02,
Hole03,
CourseID,
Groups,
ROUND((Handicap -
(SELECT MIN(Handicap) FROM Results AS t
WHERE DatePlayed='2018-11-10 00:00:00'
AND t.Groups=Results.Groups))
*.75) AS Shots
FROM
Results
WHERE
Results.DatePlayed='2018=11=10 00:00:00'

MySQL: Group By Max Value Returns Duplicate Results

I have below customer table with max qty.
I need a unique user who has max qty order by its group id.
Input:
id, customer_id, customer_group_id qty
1 1 3 1
2 1 3 10
3 1 3 5
4 2 2 10
5 2 2 1
6 2 2 2
7 3 1 5
8 3 1 10
9 4 4 1
10 4 4 2
11 4 4 2
Output should be:
id, customer_id, customer_group_id, qty
11 4 4 2
10 4 4 2 - This should be not selected
2 1 3 10
4 2 2 10
8 3 1 10
Query:
SELECT * FROM customer
WHERE qty IN ( SELECT MAX(qty) FROM customer GROUP BY customer_id)
ORDER BY customer_group_id DESC;
I tried above query but seems not working.

Query with CASE statement in Group By I need to create an entry where no results occur in the WHEN

I have a query which groups up incoming payments into date ranges (1-7 days, 3-6 months etc.) and it largely works as I had hoped. However, I want to return a row which says 0 when no income is expected in the date range.
The group by looks like this:
group by
CASE WHEN timestampdiff(day,curdate(),data.duedate) between 0 and 7 then 1
WHEN timestampdiff(day,curdate(),data.duedate) between 8 and 14 then 2
WHEN timestampdiff(day,curdate(),data.duedate) between 15 and 30 then 3
WHEN timestampdiff(month,curdate(),data.duedate) between 1 and 2 then 4
WHEN timestampdiff(month,curdate(),data.duedate) between 2 and 3 then 5
WHEN timestampdiff(month,curdate(),data.duedate) between 3 and 6 then 6
WHEN timestampdiff(month,curdate(),data.duedate) between 6 and 12 then 7
WHEN timestampdiff(year,curdate(),data.duedate) between 1 and 2 then 8
WHEN timestampdiff(year,curdate(),data.duedate) between 2 and 3 then 9
WHEN timestampdiff(year,curdate(),data.duedate) between 3 and 4 then 10
WHEN timestampdiff(year,curdate(),data.duedate) between 5 and 6 then 11
WHEN timestampdiff(year,curdate(),data.duedate) >= 7 then 12
This works correctly in that it will give me the correct amounts, but I want to force the code to give me a 0. So I currently get this:
1 300000
5 150000
8 300000
What I actually want is this:
1 300000
2 0
3 0
4 0
5 150000
6 0
7 0
8 300000
etc.
This is the entire query - I've tried using an IFNULL() but had no success:
select
sum(data.principaldue+data.interestdue) as m
from
(select
la.id
,rep.duedate
,rep.PRINCIPALDUE
,rep.INTERESTDUE
from repayment rep
join loanaccount la on la.ENCODEDKEY = rep.PARENTACCOUNTKEY
join loanproduct lp on lp.ENCODEDKEY = la.PRODUCTTYPEKEY
group by
CASE WHEN timestampdiff(day,curdate(),data.duedate) between 0 and 7 then 1
WHEN timestampdiff(day,curdate(),data.duedate) between 8 and 14 then 2
WHEN timestampdiff(day,curdate(),data.duedate) between 15 and 30 then 3
WHEN timestampdiff(month,curdate(),data.duedate) between 1 and 2 then 4
WHEN timestampdiff(month,curdate(),data.duedate) between 2 and 3 then 5
WHEN timestampdiff(month,curdate(),data.duedate) between 3 and 6 then 6
WHEN timestampdiff(month,curdate(),data.duedate) between 6 and 12 then 7
WHEN timestampdiff(year,curdate(),data.duedate) between 1 and 2 then 8
WHEN timestampdiff(year,curdate(),data.duedate) between 2 and 3 then 9
WHEN timestampdiff(year,curdate(),data.duedate) between 3 and 4 then 10
WHEN timestampdiff(year,curdate(),data.duedate) between 5 and 6 then 11
WHEN timestampdiff(year,curdate(),data.duedate) >= 7 then 12
END
Order by
CASE WHEN timestampdiff(day,curdate(),data.duedate) between 0 and 7 then 1
WHEN timestampdiff(day,curdate(),data.duedate) between 8 and 14 then 2
WHEN timestampdiff(day,curdate(),data.duedate) between 15 and 30 then 3
WHEN timestampdiff(month,curdate(),data.duedate) between 1 and 2 then 4
WHEN timestampdiff(month,curdate(),data.duedate) between 2 and 3 then 5
WHEN timestampdiff(month,curdate(),data.duedate) between 3 and 6 then 6
WHEN timestampdiff(month,curdate(),data.duedate) between 6 and 12 then 7
WHEN timestampdiff(year,curdate(),data.duedate) between 1 and 2 then 8
WHEN timestampdiff(year,curdate(),data.duedate) between 2 and 3 then 9
WHEN timestampdiff(year,curdate(),data.duedate) between 3 and 4 then 10
WHEN timestampdiff(year,curdate(),data.duedate) between 5 and 6 then 11
WHEN timestampdiff(year,curdate(),data.duedate) >= 7 then 12
END
This is not a complete answer, but would be too big for comments;
A temporary table with numbers could be useful:
MySql temporary tables:
CREATE TEMPORARY TABLE TempTable (num int);
INSERT INTO TmpTable VALUES(1,2,3,4,5,6,7,8,9,10,11,12 ...);
Then you could right join on this table to make sure missing values are included.
Lets say you have this:
results(num, val):
1 300000
5 150000
8 300000
This should result in your desired output:
SELECT numbers.num, COALESCE(results.val, 0) as val
FROM results RIGHT JOIN TempTable numbers on results.num = numbers.num
WHERE numbers.num <= 12 --or other max number
1 300000
2 0
...
5 150000
...
Hope this helps.
Edit:
If you don't have permission to create temporary tables, look for a workaround to select consecutive integers, for example:
SELECT #row := #row + 1 as row, t.*
FROM some_table t, (SELECT #row := 0) r
Where some_table is any table with enough rows.
Probably use a top N on that.
Another dirty workaround, might be good enough if you don't need many numbers:
SELECT 1 num
UNION
SELECT 2 num
UNION
...
Edit:
Slightly tidier workaround:
SELECT * FROM (VALUES (1), (2), (3), ... ) x(i)

Selecting items from one column based on values in another.

I have the following data:
id1,id2
1 3
1 8
1 10
1 11
2 3
2 10
2 11
3 2
3 18
3 20
4 3
4 8
5 3
5 10
5 11
5 40
5 45
5 50
6 1
6 59
6 70
I won't get all id1 with id2 = 3,10,11.
For example, id1=4 only with id2=3, should not return.
The results should be
id1
1
2
5
SELECT distinct(ID1) FROM TBTEST WHERE ID2 IN(3,10,11)
SQL code
SELECT ID1,COUNT(ID2) FROM TBTEST
WHERE ID2 IN(3,10,11)
GROUP BY ID1
HAVING COUNT(ID2)=3
Is this what you need?