How do I find the users biggest donation? without aggregate functions - mysql

For example given
table1
userId donation
1 50
1 150
1 340
1 20
2 85
2 15
I want
userId donation
1 340
2 85
I thought about cross joining them and see which was bigger but don't know what to do after this
SELECT * FROM
table1 as T1 cross join table1 as T2
WHERE
T1.userId = T2.userId
and
T1.donation > T2.donation

I think you are looking for something like this:
select *
from table1 T1
where not exists (
select 1
from table1 T2
where T2.userId=T1.userId and T2.donation > T1.donation
)
or the equivalent join:
select *
from table1 T1
left join table1 T2 on T2.userId=T1.userId and T2.donation > T1.donation
where T2.userId is null
If there are two rows with the same donation, both of them will be selected. If you don't want that, also compare primary key columns or some other unique keys:
T2.userId=T1.userId and (T2.donation,T2.primarykeycol1,T2.primarykeycol2) > (T1.donation,T1.primarykeycol1,T1.primarykeycol2)

You can use a self join and then compare the highest donation with the records of secondary table but same user.
SELECT T1.userId, T1.donation
FROM table1 T1
LEFT JOIN table1 T2 ON T1.userId = T2.userId AND T1.donation < T2.donation
WHERE T2.id IS NULL;
MySQL 8
WITH s1 AS (
SELECT userId,
donation,
RANK() OVER (PARTITION BY userId ORDER BY donation DESC) AS `Rank`
FROM table1
)
SELECT s1.userId, s1.donation
FROM s1
WHERE s1.`Rank` = 1;

Related

Select from 1 table sum from 2 but 1 table has a AND condition

Thanks for assisting with the previous query (SQL Query that selects a column in table 1 and uses that to select sum in table 2) of SUM from 2 tables, I now have a additional Condition for 1 of the tables. I would like to add WHERE Group1 = 1 AND IN/OUT = 'OUT'
I have 3 tables,
Names ,Groups
Names ,Payments
Names ,Payments and IN/OUT
I want to only SUM the OUT Payments in Table 3, I am getting total payments only So FAR is have:
SELECT t1.name1, SUM(t2.sale2),SUM(t3.sale3)
FROM table1 t1 JOIN table2 t2 ON t1.name1 = t2.name2
JOIN table3 t3 ON t1.name1 = t3.name3
WHERE group1 = 1
GROUP BY t1.name1
i would also like to add a zero if there is no data to sum instead of removing the whole record, Currently if a name has no payments in Table 3 but has payments in table 2 it deletes the record.
Please check the query below =>
To Get OutPayment group by Name
SELECT t1.Names,SUM(t3.Payments) As OutPayment
FROM TABLE3 as t3
INNER JOIN TABLE1 as t1 ON t1.Names = t3.Names
INNER JOIN TABLE2 as t2 ON t1.Names = t2.Names
WHERE t1.GroupID = 1 AND t3.INOROUT=2 --INOROUT =2 is OUT and 1 is IN
GROUP BY t1.Names;
To Get TotalOutPayment
SELECT SUM(t3.Payments) As TotalOutPayment
FROM TABLE3 as t3
INNER JOIN TABLE1 as t1 ON t1.Names = t3.Names
INNER JOIN TABLE2 as t2 ON t1.Names = t2.Names
WHERE t1.GroupID = 1 AND t3.INOROUT=2; --INOROUT =2 is OUT and 1 is IN
Note: Code is in DBFiddle too Check the Demo Query Link

How to select the id with max value that in another table

Here are 2 tables.
Table 1
id value
1 3
2 2
3 3
4 1
5 4
6 3
Table 2
id
1
3
4
How do I get the ids that are in Table 2 which have the max value in Table 1?
Output:
id
1
3
I already tried the following to get the max value, but I cannot figure out how to use it in a single query to get the matching rows. Because I think I need to select from the same table I just inner joined.
select max(table1.value)
from table2
inner join table1 on table1.id = table2.id;
Here is one method:
select t2.id
from (select t2.*, rank() over (order by value desc) as seqnum
from table2 t2 join
table1 t1
on t2.id = t1.id
) t
where seqnum = 1;
Or, an alternative that puts all the ids on one row:
select group_concat(t2.id) as ids
from table2 t2 join
table1 t1
on t2.id = t1.id
group by t1.value
order by t1.value desc
limit 1;
You have a couple of options available without using window functions:
You can use a WHERE clause to select only id values that have a value equal to the MAX(value) from your query and an id that is in Table2:
SELECT t1.id
FROM Table1 t1
WHERE value = (
SELECT MAX(t1.value)
FROM Table2 t2
JOIN Table1 t1 ON t1.id = t2.id
)
AND id IN (SELECT id FROM Table2)
You can JOIN your query to Table1 and Table2 again, matching the value in Table1 and the id in Table2:
SELECT t1.id
FROM (
SELECT MAX(t1.value) AS max_value
FROM Table2 t2
JOIN Table1 t1 ON t1.id = t2.id
) t
JOIN Table1 t1 ON t1.value = t.max_value
JOIN Table2 t2 ON t2.id = t1.id
In both cases the output is
id
1
3
Demo on SQLFiddle
Too low to comment but from the SQL statement you gave, you just need to add the tableid in your select parameters.
select table2.id, max(table1.value)
from table2
inner join table1 on table1.id = table2.id;

mySQL - SUM of column

I have 2 tables
table 1
id product
1 P1
2 P2
table 2
id amount product_t1
1 100 P1
2 200 P1
3 300 P2
4 400 P1
5 500 P2
I want my output to be:
product totalAmount(sum of amount)
P1 700
P2 800
EDIT: Here is my query so far
SELECT T1.product, SUM(T2.amount)
FROM table1 T1
INNER JOIN table2 T2
ON T1.product = T2.product_t1
Thanks!
you should use group by
SELECT T1.product, SUM(T2.amount)
FROM table1 T1
INNER JOIN table2 T2
ON T1.product = T2.product_t1
GROUP BY product
Since you're not using foreign keys you don't even need the table 1 for the desired result.
SELECT
product_t1 AS product,
SUM(amount) AS totalAmount
FROM table2
GROUP BY product_t1
What you're missing is the GROUP BY statement in order to get a separate row for each individual product
SELECT T1.product, SUM(T2.amount)
FROM table1 T1
INNER JOIN table2 T2
ON T1.product = T2.product_t1
GROUP BY product T1.product
Use the GROUP BY tag . Group by helps to group your result via value of product
Try to play with GROUP BY and AS
SELECT product_t1 as product, SUM(amount) AS totalAmount FROM table2
GROUP BY product
https://dev.mysql.com/doc/refman/5.7/en/group-by-modifiers.html
OR add to your code group by
SELECT T1.product, SUM(T2.amount)
FROM table1 T1
INNER JOIN table2 T2 ONT1.product = T2.product_t1
Gruop by T1.product

Joining three tables such that extra matches are discarded?

How can I write a query to give the results of three tables such that there's only one result per "line"?
The tables are:
T1 (ID, name, IP)
T2 (ID, date_joined)
T3 (ID, address, date_modified)
The relations are:
T1-T2 1:1, T1-T3 1:M - there can be many address rows per ID in T3.
What I want is a listing of all users with the fields above, but IF they have an address, I only want to record ONE (bonus would be if it is the latest one based on T3.date_modified).
So I should end up with exactly the number of records in T1 (happens to be equal to T2 in this case) and no more.
I tried:
select t.ID, t.name, t.IP, tt.ID, tt.date_joined, ttt.ID, ttt.address
from T1 t JOIN T2 tt ON (t.ID = tt.ID) JOIN T3 ttt ON (t.ID = ttt.ID)
And every sensible combination of LEFT, RIGHT, INNER, etc joins I could think of! I keep getting multiple duplicate because of T3
This query should work:
select
t1.ID, t1.name, t1.IP, t2.date_joined, t3x.address
from t1
join t2 on t1.ID = t2.id
left join (
select t3.*
from t3
join (
select id, max(date_modified) max_date
from t3
group by id
) max_t3 on t3.id = max_t3.id and t3.date_modified = max_t3.max_date
) t3x on t1.ID = t3x.id
First you do the normal join between t1 and t2 and then you left join with a derived table (t3x) that is the set of t3 rows having the latest date.
So T2 is actually not relevant here. You just need a way to join from T1 to T3 in a way that gets you at most one T3 row per T1 row.
One way of doing this would be:
select
T1.*,
(select address from T3 where T3.ID=T1.ID order by date_modified desc limit 1)
from T1;
This won't likely be very efficient, being a correlated subquery, but you may not care depending on the size of your dataset.
It's also only good for getting one column from T3, so if you had Address, City, and State, you'd have to figure out something else.
You can use sub query with Top 1 so that u get only one result from T3
here is a sample sql
select * into #T1 from(
select 1 ID
union select 2
union select 3) A
select * into #T2 from(
select 1 ID
union select 2
union select 3) A
select * into #T3 from(
select 1 ID, 'ABC' Address, getDate() dateModified
union select 1, 'DEF', getDate()
union select 3, 'GHI', getDate()) A
select *, (select top 1 Address from #T3 T3 where T3.ID= T1.ID order by datemodified desc) from #T1 T1
inner join #T2 T2 on T1.ID = T2.ID
Bonus :- you can also add order by dateModified desc to get the latest address

How to retrieve the not common values from 2 tables?

I have the 2 following tables t1, t2 with values,
t1 t2
1 4
2 2
3 3
Now I want to output
1
4
How can I get this output in select query ?
This will get you each item from t1 that is not present in t2, and each item in t2 that is not present in t1:
select t1.id from t1
left join t2 on t2.id = t1.id
where t2.id is null
union all
select t2.id from t2
left join t1 on t1.id = t2.id
where t1.id is null
(I have assumed that the field name in each table is named id just for the sake of being able to write a query against the tables.)
Another way would be:
select coalesce(t1.id, t2.id)
from t1
full outer join t2 on t2.id = t1.id
where t1.id is null or t2.id is null
Another way. Just COUNT them.
This works if the values are unique per table
SELECT
CombinedValue
FROM
(
SELECT t1 AS CombinedValue FROM t1
UNION ALL
SELECT t2 FROM t2
) foo
GROUP BY
CombinedValue
HAVING
COUNT(*) = 1
If not unique per table
SELECT
CombinedValue
FROM
(
SELECT DISTINCT t1 AS CombinedValue FROM t1
UNION ALL
SELECT DISTINCT t2 FROM t2
) foo
GROUP BY
CombinedValue
HAVING
COUNT(*) = 1
you can use Joins in MySql to proceed and to obtain result.
this will help you
http://www.techrepublic.com/article/sql-basics-query-multiple-tables/1050307