Getting wrong data from DB when joining MySql [duplicate] - mysql

I have a table of revenue as
title_id revenue cost
1 10 5
2 10 5
3 10 5
4 10 5
1 20 6
2 20 6
3 20 6
4 20 6
when i execute this query
SELECT SUM(revenue),SUM(cost)
FROM revenue
GROUP BY revenue.title_id
it produces result
title_id revenue cost
1 30 11
2 30 11
3 30 11
4 30 11
which is ok, now i want to combine sum result with another table which has structure like this
title_id interest
1 10
2 10
3 10
4 10
1 20
2 20
3 20
4 20
when i execute join with aggregate function like this
SELECT SUM(revenue),SUM(cost),SUM(interest)
FROM revenue
LEFT JOIN fund ON revenue.title_id = fund.title_id
GROUP BY revenue.title_id,fund.title_id
it double the result
title_id revenue cost interest
1 60 22 60
2 60 22 60
3 60 22 60
4 60 22 60
I can't understand why is it double it,please help

Its doubling because you have title repeated in fund and revenue tables. This multiplies the number of records where it matches. This is pretty easy to see if you remove the aggregate functions and look at the raw data. See here
The way to get around this is to create inline views of your aggregates and join on the those results.
SELECT R.title_id,
R.revenue,
R.cost,
F.interest
FROM (SELECT title_id,
Sum(revenue) revenue,
Sum(cost) cost
FROM revenue
GROUP BY revenue.title_id) r
LEFT JOIN (SELECT title_id,
Sum(interest) interest
FROM fund
GROUP BY title_id) f
ON r.title_id = F.title_id
output
| TITLE_ID | REVENUE | COST | INTEREST |
----------------------------------------
| 1 | 30 | 11 | 30 |
| 2 | 30 | 11 | 30 |
| 3 | 30 | 11 | 30 |
| 4 | 30 | 11 | 30 |
demo

The reason for this is that you have joined the table the first derived table from the second table without grouping it. To solve the problem, group the second table (fund) and join it with the first derived table using LEFT JOIN.
SELECT b.title_id,
b.TotalRevenue,
b.TotalCost,
d.TotalInterest
FROM
(
SELECT a.title_id,
SUM(a.revenue) TotalRevenue,
SUM(a.cost) TotalCost
FROM revenue a
GROUP BY a.title_id
) b LEFT JOIN
(
SELECT c.title_id,
SUM(a.interest) TotalInterest
FROM fund c
GROUP BY c.title_id
) d ON b.title_id = d.title_id

There are two rows for each title_id in revenue table.

Related

How to count the total amount of similar rows in a MySQL query

I need help with a MySQL query to count the number of times a combination of the same age_from and age_to occur.
Sample data:
age_from age_to
+---------+-------+
18 | 100
30 | 75
18 | 50
18 | 100
30 | 75
18 | 50
30 | 75
+---------+------+
Desired result:
18 to 100 = 2
30 to 75 = 3
18 to 50 = 2
I have already tried this:
SELECT
`p_age_from` AS `age_from`,
`p_age_to` AS `age_to`,
COUNT(`p_age_from`) AS `user_count`
FROM `user`
GROUP BY `p_age_from`, `p_age_to`
ORDER BY `p_age_from`
You can use CONCAT to join the age_from and age_to values. Then use this to group and count the data:
SELECT
CONCAT(`age_from`,' to ',`age_to`) as 'grouping',
COUNT('grouping') AS `user_count`
FROM `user`
GROUP BY grouping
You can get your result using following query
SELECT CONCAT(age_from,' to ',age_to,' = ',count(age_to)) as 'age_from to age_to'
FROM user
GROUP BY age_from, age_to
ORDER BY age_from;

How i can get values order by the count of distinct values

I want to get those Product in ascending order who number is greater in mysql
order_id | product_id
1 | 13
1 | 12
1 | 24
2 | 14
2 | 245
2 | 23
3 | 14
3 | 23
4 | 14
i have done that code but its not working
SELECT product_id FROM `sales_order_item` ORDER BY COUNT('product_id') ASC
i want priduct_id in ascending order on the basis of there count\
product_id
14
23
13
24
245
as 14 occurs 4 times it must have to be on top and so on
use order by COUNT('product_id') desc
SELECT product_id,COUNT('product_id') as cnt FROM `sales_order_item`
group by product_id
ORDER BY cnt desc

Select min/max from multiple items

I'll try to explain it as simple as possible:
First some database structure with dummy data.
Structure
tb_spec_fk
feature value
-----------------
1 1
1 2
1 3
1 4
1 5
2 2
2 3
3 1
3 4
4 2
4 3
4 4
5 1
5 3
5 5
6 3
6 5
tb_spec_feature
feature_id filter
------------------
1 2
2 2
3 2
4 2
5 1
6 0
tb_spec_value
value_id name
----------------
1 10
2 20
3 30
4 40
5 50
Now, what I want is the follow result
Result
feature_id min_value max_value
---------------------------------
1 10 50
2 20 30
3 10 40
4 20 40
But how?
Logic
Get from the tb_spec_feature where "filter" equals 2 the highest and lowest values which are present in the tb_spec_value table and connected together trough the tb_spec_fk table.
My attemps
A lot! But I'll spare you :)
SELECT
f.feature_id AS feature_id,
MAX(value.name) AS max_value,
MIN(value.name) AS min_value
FROM tb_spec_feature AS f
JOIN tb_spec_fk AS fk ON f.feature_id=fk.feature
JOIN tb_spec_value AS value ON fk.value=value.id
WHERE f.filter=2
GROUP BY f.feature_id
The two JOIN statements "link" the a feature to a value. GROUP BY groups all rows with the same feature id, and then you can take the min or max or any other aggregate function on those columns.
Demo
Here is how you can do it
select
tsf.feature_id,
tsvl.name as Min_Value,
tsvr.name as Max_Value
from tb_spec_feature as tsf
inner join (select feature , MIN(value) MinV,MAX(value)MaxV from tb_spec_fk group by feature order by feature)as tsfkl on tsfkl.feature = tsf.feature_id
left join tb_spec_value as tsvl on tsvl.value_id = tsfkl.MinV
left join tb_spec_value as tsvr on tsvr.value_id = tsfkl.MaxV
where tsf.filter = 2
group by tsf.feature_id
Output
feature_id | Min_Value | Max_Value
---------------------------------
1 | 10 | 50
2 | 20 | 30
3 | 10 | 40
4 | 20 | 40
Fiddle Demo

Mysql join and sum is doubling result

I have a table of revenue as
title_id revenue cost
1 10 5
2 10 5
3 10 5
4 10 5
1 20 6
2 20 6
3 20 6
4 20 6
when i execute this query
SELECT SUM(revenue),SUM(cost)
FROM revenue
GROUP BY revenue.title_id
it produces result
title_id revenue cost
1 30 11
2 30 11
3 30 11
4 30 11
which is ok, now i want to combine sum result with another table which has structure like this
title_id interest
1 10
2 10
3 10
4 10
1 20
2 20
3 20
4 20
when i execute join with aggregate function like this
SELECT SUM(revenue),SUM(cost),SUM(interest)
FROM revenue
LEFT JOIN fund ON revenue.title_id = fund.title_id
GROUP BY revenue.title_id,fund.title_id
it double the result
title_id revenue cost interest
1 60 22 60
2 60 22 60
3 60 22 60
4 60 22 60
I can't understand why is it double it,please help
Its doubling because you have title repeated in fund and revenue tables. This multiplies the number of records where it matches. This is pretty easy to see if you remove the aggregate functions and look at the raw data. See here
The way to get around this is to create inline views of your aggregates and join on the those results.
SELECT R.title_id,
R.revenue,
R.cost,
F.interest
FROM (SELECT title_id,
Sum(revenue) revenue,
Sum(cost) cost
FROM revenue
GROUP BY revenue.title_id) r
LEFT JOIN (SELECT title_id,
Sum(interest) interest
FROM fund
GROUP BY title_id) f
ON r.title_id = F.title_id
output
| TITLE_ID | REVENUE | COST | INTEREST |
----------------------------------------
| 1 | 30 | 11 | 30 |
| 2 | 30 | 11 | 30 |
| 3 | 30 | 11 | 30 |
| 4 | 30 | 11 | 30 |
demo
The reason for this is that you have joined the table the first derived table from the second table without grouping it. To solve the problem, group the second table (fund) and join it with the first derived table using LEFT JOIN.
SELECT b.title_id,
b.TotalRevenue,
b.TotalCost,
d.TotalInterest
FROM
(
SELECT a.title_id,
SUM(a.revenue) TotalRevenue,
SUM(a.cost) TotalCost
FROM revenue a
GROUP BY a.title_id
) b LEFT JOIN
(
SELECT c.title_id,
SUM(a.interest) TotalInterest
FROM fund c
GROUP BY c.title_id
) d ON b.title_id = d.title_id
There are two rows for each title_id in revenue table.

MySQL : Get max values of groups

I have a table:
user_id | fav_song_genre | votes_as_fav_member
--------+----------------+--------------------
1 | hip hop | 3
2 | hip hop | 5
3 | rock | 8
4 | rock | 6
How do I get only results of user_id's with the highest votes_as_fav_member per group fav_song_genre:
Something like
SELECT *, MAX(votes_as_fav_member) as most_votes
FROM table
GROUP BY
fav_song_genre
I'm using that but it's not giving me the ID's of the members with most votes per genre.
This is not a problem of MySQL, rather a bit of logic problem with your approach.
Let's say we have the following:
user_id | fav_song_genre | votes_as_fav_member
--------+----------------+--------------------
1 | hip hop | 3
2 | hip hop | 5
3 | rock | 8
4 | rock | 6
5 | hip hop | 5
6 | rock | 8
Which ID should the query return? Should it return only one? or all that have the same amount of votes?
So, if you require only a single ID, what is the differentiation of a draw?
Lieven beat me to the SQL resolution by a few seconds, though.
Reasoning goes like
SELECT max vote for each genre
JOIN back with the original table to retrieve the additional columns for the records found.
SQL Statement
SELECT us.*
FROM UserSongs us
INNER JOIN (
SELECT fav_song_genre
, MAX(votes_as_fav_member) AS votes_as_fav_member
FROM UserSongs
GROUP BY
fav_song_genre
) usm ON usm.fav_song_genre = us.fav_song_genre
AND usm.votes_as_fav_member = us.votes_as_fav_member
Edit
How can I make sure the person with the lower ID is returned
SELECT MIN(us.user_id) as user_id
, us.fav_song_genre
, us.votes_as_fav_member
FROM UserSongs us
INNER JOIN (
SELECT fav_song_genre
, MAX(votes_as_fav_member) AS votes_as_fav_member
FROM UserSongs
GROUP BY
fav_song_genre
) usm ON usm.fav_song_genre = us.fav_song_genre
AND usm.votes_as_fav_member = us.votes_as_fav_member
GROUP BY
us.fav_song_genre
, votes_as_fav_member
Not sure if that's what you are asking:
SELECT g.fav_song_genre
, t.user_id
, g.most_votes
FROM yourTable t
JOIN
( SELECT fav_song_genre
, MAX(votes_as_fav_member) as most_votes
FROM yourTable
GROUP BY fav_song_genre
) AS g
ON t.fav_song_genre = g.fav_song_genre
AND t.votes_as_fav_member= g.most_votes
;
I created the table and tested, and I think this will also work
Table Data:
user_id fav_song_genre votes_as_fav_member
1 hip_hop 3
2 hip_hop 5
3 rock 8
4 rock 6
5 blues 20
6 indie 18
7 rock 35
8 country 33
9 hip_hop 35
10 indie 5
11 blues 7
12 hip_hop 59
13 indie 187
14 classic 45
15 country 61
16 hip_hop 243
Query:
select t.user_id, t.fav_song_genre, t.votes_as_fav_member
from (
select user_id, max(votes_as_fav_member) as max_votes, fav_song_genre
from table1 group by fav_song_genre
)
as x inner join table1 as t on t.votes_as_fav_member = x.max_votes and t.fav_song_genre = x.fav_song_genre;
Results:
user_id fav_song_genre votes_as_fav_member
5 blues 20
7 rock 35
13 indie 187
14 classic 45
15 country 61
16 hip_hop 243