sql basic join table - mysql

ID Date Spend
1 01/01/1990 $x1
2 01/01/1990 $x2
2 01/03/1990 $x3
I'm a sql beginner and could someone help me to solve this question?I'd appreciate it!
if we want to just consider the date after the year of 2000, how can we find the ID which has tenth highest spend by using the method of Join?
Using my basic sql knowledge,this is what I have coded:
select ID, SUM(Spend)
From(
select ID,SUM(Spend)
from table A, table B
WHERE A.ID=B.ID
AND Date => 01/01/2000;
)
Order by SUM(Spend) DESC
LIMIT 10;

Here's an example:
select a.ID
, SUM(Spend) as SumSpend
from tableA a
join tableB b
on a.ID = b.ID
where '2000-01-01' <= date
group by
a.ID
order by
SumSpend desc
limit 1
offset 2
group by tells MySQL which groups of rows to sum
You can use limit 1 offset 9 to get the tenth row
If you select a column that is in two tables, you have to specify which table (a.ID above)
In SQL a date is a string in single quotes

Related

mysql finding the sum of subgroup maximums

If I have the following table in MySQL:
date type amount
2017-12-01 3 2
2018-01-01 1 100
2018-02-01 1 50
2018-03-01 2 2000
2018-04-01 2 4000
2018-05-01 3 2
2018-06-01 3 1
...is there a way to find the sum of the amounts corresponding to the latest dates of each type? There are guaranteed to be no duplicate dates for any given type.
The answer I'd be looking to get from the data above could broken down like this:
The latest date for type 1 is 2018-02-01, where the amount is 50;
The latest date for type 2 is 2018-04-01, where the amount is 4000;
The latest date for type 3 is 2018-06-01, where the amount is 1;
50 + 4000 + 1 = 4051
Is there a way to arrive directly at 4051 in a single query? This is for a Django project using MySQL if that makes a difference; I wasn't able to find an ORM-related solution either, so figured a raw SQL query might be a better place to start.
Thanks!
Not sure for Django but in raw sql you could use a self join to pick latest row for each type based on latest date and then aggregate your results to get the sum of amounts for each type
select sum(a.amount)
from your_table a
left join your_table b on a.type = b.type
and a.date < b.date
where b.type is null
Demo
Or
select sum(a.amount)
from your_table a
join (
select type, max(date) max_date
from your_table
group by type
) b on a.type = b.type
and a.date = b.max_date
Demo
Or by using a correlated subuery
select sum(a.amount)
from your_table a
where a.date = (
select max(date)
from your_table
where type = a.type
)
Demo
For Mysql 8 you can use window functions to get you desired result as
select sum(amount)
from (select *, row_number() over (partition by type order by date desc) as seq
from your_table
) t
where seq = 1;
Demo

Fetch only 2 results, one for each different value of a concrete field

In a MYSQL table with those 5 fields: id, user_id, date, type, uid where type can be 1 or 2, I'm looking for a single query where I can fetch 2 results, one for type=1 and another one for type=2 based on date field.
Right now i have the following query which only gives me the last uid without taking care of the type field.
SELECT t.uid
FROM table AS t
WHERE t.user_id = 666
ORDER BY t.date
DESC LIMIT 1
Does anyone know how should modify this query so i can get the last uid for type=1 and the last one for type=2 based on date field? I would like to keep a a single query
Union all is probably the simplest method:
(select t.*
from t
where t.user_id = 666 and t.type = 1
order by date desc
limit 1
) union all
(select t.*
from t
where t.user_id = 666 and t.type = 2
order by date desc
limit 1
)
Finally i updated the query following this "paradigm":
http://dev.mysql.com/doc/refman/5.7/en/example-maximum-column-group-row.html
http://jan.kneschke.de/projects/mysql/groupwise-max/
This is how the query ended up:
SELECT s1.type, s1.uid
FROM t AS s1
LEFT JOIN t AS s2 ON s1.type = s2.type AND s1.date < s2.date
WHERE s2.date IS NULL;
Here's a visual example: http://hastebin.com/ibinidasuw.vhdl
Credits are for snoyes from #sql on Freenode. :)

Grouping users by group ids in mysql, exclude specified userid from the results?

There is a small application that I've been tasked on, that deals with getting latest posts in a group. In this sample below, I have there is a MySQL table formatted as such:
groupid userid date_updated
1 1 [date]
1 2 [date]
2 1 [date]
2 2 [date]
2 3 [date]
...
How do I do an SQL statement as such as the results go out in this manner (assuming I give a userid with a value of 1 for example):
groupid userid date
1 2 [date]
2 2 [date]
2 3 [date]
These are all ordered by date. As you may have noticed, the results do not include the provided userid (as the requirement is only to get users other than the supplied user ID). In other words, show only users other than the specified user in groups where the specified user is part of.
Is it possible to do this in a single SQL statement?
Search select query with where
select * from table where userid != '1'
Try the following solution.
select
tbl.*
from
tbl INNER JOIN
(select groupid, userid, max(date_updated)
from tbl
group by groupid, userid) tbl2
USING(groupid, userid)
ORDER BY tbl.date_updated;
You can use this
SELECT tbl.* FROM (SELECT * FROM tablename ORDER BY date DESC) as tbl GROUP BY tbl.groupid
I managed to find a possible answer to my question here with this SQL statement:
SELECT a.groupid, a.userid, a.date_updated
FROM group_participants a
WHERE a.groupid IN (
SELECT DISTINCT b.groupid FROM group_participants b WHERE b.userid = 1
)
AND a.user_id <> 1
GROUP BY a.userid
ORDER by a.date_updated DESC
Thank you guys those SQL statements you posted, gave me an idea. I don't know if the SQL statement above can still be optimized, but this one above gave me the correct answer.

MySQL select top ten records with no duplicate uid

I have the following table (user_record) with millions of rows like this:
no uid s
================
1 a 999
2 b 899
3 c 1234
4 a 1322
5 b 933
-----------------
The uid can be duplicate .What I need is to show the top ten records(need inclued uid and s) with no duplicate uid order by s (desc). I can do this by two steps in the following SQL statements:
SELECT distinct(uid) FROM user_record ORDER BY s DESC LIMIT 10
SELECT uid,s FROM user_record WHERE uid IN(Just Results)
I just wana know is there a bit more efficient way in one statement?
Any help is greatly appreciated.
ps:I also have following the SQL statement:
select * from(select uid,s from user_record order by s desc) as tb group by tb.uid order by tb.s desc limit 10
but it's slow
The simpliest would be by using MAX() to get the highest s for every uid and sorted it based on the highest s.
SELECT uid, MAX(s) max_s
FROM TableName
GROUP BY uid
ORDER BY max_s DESC
LIMIT 10
SQLFiddle Demo
The disadvantage of the query above is that it doesn't handles duplicates if for instance there are multiple uid that have the same s and turn out to be the highest value. If you want to get the highest value s with duplicate, you can do by calculating it on the subquery and joining the result on the original table.
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT DISTINCT s
FROM TableName
ORDER BY s DESC
LIMIT 10
) b ON a.s = b.s
ORDER BY s DESC

Get last record in each group and SUM some of them

i have a problem with sql query to mysql to take the last record in each group and sum some field in one query.i have a table:
name date interested made_call
andrew.h 2011-02-04 10 10
andrew.h 2011-02-11 20 10
andrew.h 2011-02-13 2 10
sasha.g 2011-02-11 5 20
sasha.g 2011-02-12 5 1
i need to sum made_call column grouping by name and return the last record from interested.
here what i want to get in result:
name date interested made_call
andrew.h 2011-02-13 2 30
sasha.g 2011-02-12 5 21
i tried to get result with this query
SELECT a.name,a.date,a.interested,sum(made_call) as made_call
FROM `resultboard` a
WHERE a.attendence = 1
AND NOT EXISTS (select 1 from resultboard where name = a.name
and id > a.id and attendence = 1)
GROUP BY name
but in result i got
andrew.h 2011-02-13 2 10
sasha.g 2011-02-12 5 1
so the query didnot sum, just return the last record from group
help)
That may be a little slow if the table is very big, but it will get the wanted result:
SELECT a.name, t.date, a.interested, t.calls
FROM resultboard a
JOIN (SELECT name, MAX(date) AS date, SUM(made_call) AS calls FROM resultboard
GROUP BY name) AS t
ON a.name = t.name AND a.date = t.date
Your WHERE clause is eliminating all but the last row from consideration as part of the sum.
In some other DB's you could use the LAST aggregate function. MySQL doesn't have that, but you can emulate it like so for your case:
SELECT
a.name,
SUBSTRING_INDEX(
GROUP_CONCAT(CAST(a.date AS CHAR) ORDER BY date desc),
',', 1
) AS date,
SUBSTRING_INDEX(
GROUP_CONCAT(CAST(a.interested AS CHAR) ORDER BY date desc),
',', 1
) AS interested,
sum(made_call) as made_call
FROM `resultboard` a
WHERE a.attendence = 1
GROUP BY name
It might not be fast on large data sets, but it should at least do the job if my research is correct. I haven't tested this, so YMMV.
I think that using WITH ROLLUP for GROUP BY modifier may help you. http://dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html
Edit; I got i wrong , no need for WITH ROLLUP
SELECT r.name,
MAX(r.date) as date,
(SELECT r2.interested FROM resultboard r2 WHERE r2.name = r.name ORDER BY r.date DESC LIMIT 1),
SUM(made_call) as made_call
FROM resultboard r
GROUP BY name;