Fetch rows with MAX DATE and GROUP BY - mysql

I have a table name payment_schedule with following contents
I want to fetch records with MAX(due_date) GROUPED BY loan_application_id
With reference to records in above image, i expect the result to be following
I tried using following SQL query
SELECT
id,
MAX(due_date) as due_date,
loan_application_id
FROM
payment_schedule
GROUP BY
loan_application_id
Which returns me the following result.
As you see it does not return the corresponding id for a given due date.
Additionally, I have another column called payment_type_id and I need to exclude rows when payment_type_id has value of 3.
I tried several solution available here, nothing seems to work, how to go about it?
Thanks.

This is called Group-wise Maximum and tagged here as greatest-n-per-group. The most traditional approach is to find the value you want and do a join to get the corresponding row per group like this:
SELECT
ps.id,
ps.due_date,
ps.loan_application_id
FROM
(
SELECT
MAX(due_date) as due_date,
loan_application_id
FROM payment_schedule
WHERE payment_type_id != '3'
GROUP BY loan_application_id
) ps2
LEFT JOIN payment_schedule ps USING (loan_application_id)
WHERE ps.due_date = ps2.due_date
AND ps.payment_type_id != '3'
GROUP BY ps.loan_application_id
It's also worth mentioning that this query will run a bazillion times faster if you have an index on your loan_application_id and due_date columns.
Best discussion I've seen here on SO is this: Select first row in each GROUP BY group?
Also addressed in the official docs here: http://dev.mysql.com/doc/refman/5.7/en/example-maximum-column-group-row.html

If due date per loan_application_id is distinct, you can remove the keyword distinct below:
select distinct a.*
from payment_schedule a, (
select loan_application_id, max(due_date) max_date
from payment_schedule
where payment_type_id <> 3
group by 1
) as b
where a.loan_application_id = b.loan_application_id
and a.due_date = b.max_date

In most databases, this is easiest using window functions. In MySQL, you can use a join and group by:
select ps.*
from payment_schedule ps join
(select load_application_id, max(due_date) as maxdd
from payment_schedule
group by load_application_id
) l
on ps.load_application_id = l.load_application_id and ps.due_date = l.maxdd;

Related

Mysql subquery field unknown

I have read many posts have a solution for this but this does not work in my case. What am I doing wrong?
- This gives me the SUM of scores for every user and this is the first part.( Aggregated Data)
The Query result
SELECT user_id, sum(score) as total_user_score
FROM (
SELECT comments_proper.user_id, comments_proper.score
FROM assignment_2.comments_proper
) AS rsch
GROUP BY user_id;
However, I want only 2 records which contain the min and the max score values.
What am I doing wrong?
Oh dear, where to begin.
I have read many posts
You should have been paying attention to which ones got up-voted and good answers, and which were down-voted/closed. The former would have included the table structures, examples of input and expected output. And unambiguous questions.
I want only 2 records
Is that from the source data set or from the aggregated data set?
The latter is a slightly tricky problem which has been asked and answered many times here on SO, there are multiple solutions with different performance characteristics. There's even a chapter in the manual covering just this question. The current content at that link uses subqueries to identify the min/max value which replaces an earlier version of the documentation which explained the max-concat trick, but its also possible to use variables to identify the right caddidate rows in a sub-query or to use sorting.
However the SQL you've shown us here, has very little to do with solving the problem you describe, and is very badly written.
I won't provide examples of every solution, but this will solve your problem...
SELECT user_id, SUM(score)
FROM assignment_2.comments_proper
GROUP BY user_id
ORDER BY SUM(score)
UNION
SELECT user_id, SUM(score)
FROM assignment_2.comments_proper
GROUP BY user_id
ORDER BY SUM(score)
updated
I hadn't tested the above. I did test this:
SELECT *
FROM (
SELECT user_id, SUM(score)
FROM assignment_2.comments_proper
GROUP BY user_id
ORDER BY SUM(score) LIMIT 0,1
) as lowest
UNION ALL
SELECT *
FROM (
SELECT user_id, SUM(score)
FROM assignment_2.comments_proper
GROUP BY user_id
ORDER BY SUM(score) DESC LIMIT 0,1
) as highest
In your queries you have some problem of sintax and a too complex calculation for aggregated resul anyway .. in cp1.* result you have the min related values in cp2.* the max related.
If you need all the resuly for min and max rows on the same row you can use a couple of inner join based on the aggregated result
select cp1.* , cp2.*
from ( SELECT cp.user_id, sum(cp.score), min(cp.score) min_score, max(cp.score) max_score
FROM assignment_2.comments_proper cp
group by cp.user_id ) t
inner join assignment_2.comments_proper cp1 on cp1.user_id = t.user_id
and cp1.score = t.min_score
inner join assignment_2.comments_proper cp2 on cp2.user_id = t.user_id
and cp2.score = t.max_score
otherwise if you want the result in two rows one for min and one for max
select 'min' , cp1.*
from ( SELECT cp.user_id, sum(cp.score), min(cp.score) min_score, max(cp.score) max_score
FROM assignment_2.comments_proper cp
group by cp.user_id ) t
inner join assignment_2.comments_proper cp1 on cp1.user_id = t.user_id
and cp1.score = t.min_score
union
select 'max' , cp2.*
from ( SELECT cp.user_id, sum(cp.score), min(cp.score) min_score, max(cp.score) max_score
FROM assignment_2.comments_proper cp
group by cp.user_id ) t
inner join assignment_2.comments_proper cp2 on cp2.user_id = t.user_id
and cp2.score = t.max_score

MYSQL - GROUP BY 2 COLUMN ORDER BY CREATION DATE

I'm trying to get all results of my table with a GROUP BY on 2 columns and get the last insertions.
"Prices" table :
My Request :
SELECT DISTINCT p.*
FROM prices p
JOIN (
SELECT MAX(created_at) as "last_created"
FROM prices
WHERE station_id = 27210003
GROUP BY station_id, fuel_id) as sub
ON sub.last_created = p.created_at
WHERE p.station_id = 27210003
GROUP BY p.station_id, p.fuel_id
Results are 3 lines but wrong line because not last created in my DB -_-'
Please help me !!! >_<'
Thx
Since you're selecting a specific station_id in the WHERE clause, you don't need to include that in GROUP BY.
The subquery has to return the columns you're grouping on, and then you have to include them in the ON clause.
And you don't need GROUP BY in the outer query, since the JOIN should ensure that there's just one row for each fuel_id (unless there are duplicate created_at for the same fuel_id and station_id).
SELECT DISTINCT p.*
FROM prices p
JOIN (
SELECT fuel_id, MAX(created_at) as "last_created"
FROM prices
WHERE station_id = 27210003
GROUP BY fuel_id) as sub
ON sub.last_created = p.created_at AND sub.fuel_id = p.fuel_id
WHERE p.station_id = 27210003

MySQL Group two column with where clause on both two group

What I have:
I have two table , first is user_faktorha save invoices data and second is u_payment save payment data .
What I want:
I want to group all data from this two table and have a result as one table with sum both table.
My two table with sample query's is on sqlfiddle : http://sqlfiddle.com/#!2/b9f9e/4
What's problem:
I try to solve this problem , but give wrong result each time , for example (can be see on sqlfiddle) , user/tell named as habib on give wrong sum(price) result.
habib's faktorhaprice = -508261 and habib's paymentprice = 648000 but sum result in main query have wrong data -7115654 and 13000000
what's the solution ?
(Updated) One way:
SELECT tell,SUM(FAKTORHAPRICE) FAKTORHAPRICE, SUM(PaymentPrice) PaymentPrice
FROM (SELECT tell, price as FAKTORHAPRICE, null PaymentPrice
from user_faktorha
union all
SELECT Username as tell, null as FAKTORHAPRICE, Price as PaymentPrice
FROM `u_payment` WHERE Active='1') sq
GROUP BY tell ORDER BY FAKTORHAPRICE ASC;
SQLFiddle here.
The essence of your problem here is that you are trying to relate to unrelated tables. Sure they have common data in the user name, but there is not a clean relation between them like an invoice id that can be used to relate the items together such that the OUTER JOIN wouldn't duplicate records in your result set. My suggestion would be to do the aggregation on each table individually and then join the results like this:
SELECT f.tell, f.faktorhaprice, p.paymentprice
FROM
(SELECT tell, SUM(price) AS faktorhaprice FROM user_faktorha GROUP BY tell) AS f
INNER JOIN
(SELECT username, SUM(price) AS paymentprice FROM u_payment GROUP BY username) AS p
ON f.tell = p.username

MySQL's count(*) doesn't work properly

I want to count all rows from the game_votes where g_id is equal to 14, it is working almost good, but if there aren't any records with g_id = 14 it does still show 1 in the cnt field.
Here is my query:
SELECT
SUM(vote) as vote,
COUNT(*) as cnt
FROM (`games`)
LEFT JOIN `game_votes`
ON
`game_votes`.`g_id` = `games`.`id`
WHERE `games`.`id` = '14'
Whats wrong? Am I missing something?
You're getting a count of 1 because COUNT(*) essentially counts the number of rows in your result set. Since you're selecting a row out of your games table with an id of 14 and left joining that to the game_votes table, you're going to always have 1 or more rows as long as there exists a game with an id of 14 regardless of whether or not it contains any corresponding votes in your game_votes table. Instead of COUNT(*), try COUNT(game_votes.g_id). If there are no votes, the g_id field will contain a null value, and COUNT() will not include a null value in its calculation.
Check the result of
SELECT *
FROM (`games`)
LEFT JOIN `game_votes`
ON
`game_votes`.`g_id` = `games`.`id`
WHERE `games`.`id` = '14'
and you will see that your using LEFT JOIN (instead of JOIN) is the cause.
SELECT SUM(vote) as vote, COUNT(*) as cnt from games,game_votes where game_votes.g_id=games.id and games.id=14;
This should work
The MySQL SUM function requires a GROUP BY ... see http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html

Subquery returns more than 1 row

im geting this error when trying to do 2 counts inside of my query
first ill show you the query:
$sql = mysql_query("select c.id, c.number, d.name,
(select count(*) from `parts` where `id_container`=c.id group by `id_car`) as packcount,
(select count(*) from `parts` where `id_container`=c.id) as partcount
from `containers` as c
left join `destinations` as d on (d.id = c.id_destination)
order by c.number asc") or die(mysql_error());
now the parts table has 2 fields that i need to use in the count:
id_car
id_container
id_car = the ID of the car the part is for
id_container = the ID of the container the part is in
for packcount all i want is a count of the total cars per container
for partcount all i want it a count of the total parts per container
It's because of GROUP BY You're using
Try something like
(select count(distinct id_car) from `parts` where `id_container`=c.id)
in You're subquery (can't check right now)
EDIT
PFY - I think UNIQUE is for indexes
Your grouping in your first sub-query is causing multiple rows to be returned, you will probably need to run separate queries to get the results you are looking for.
This subquery may return more than one row.
(select count(*) from `parts` where `id_container`=c.id group by `id_car`) as packcount, ...
so, i'd suggest to try something of the following:
(select count(DISTINCT `id_car`) from `parts` where `id_container`=c.id) as packcount, ...
see: COUNT(DISTINCT) on dev.mysql.com
and: QA on stackoverflow