How to only get DISTINCT rows from a JOIN query: MySQL - mysql

Two tables. Table one is users. Table two is user events. One user has many events. I just want to get a list of the users with the most recent events. I can obviously set it to select more rows than I need and filter out the duplicates but I really want to just select the exact number of rows I need in the SQL.
This SQL query gives duplicates of a.name where one user has had more than one event recently. I thought that DISTINCT would prevent duplicates. What am I doing wrong? How do I just get one row for each user?
SELECT DISTINCT (a.name), b.date , a.id
FROM `users` a
INNER JOIN events b
ON a.id = b.userid
WHERE now() > b.date
ORDER BY b.date DESC, a.id DESC
LIMIT 30;
Table users...
id name
Table events...
id userid date
I don't need to select the b.date value but this is needed for DISTINCT to work because it is in the ORDER BY part, I believe.

You could GROUP BY the user and only take the maximum date (or the minimum, if you want the oldest of the events).
SELECT a.name,
max(b.date) date,
a.id
FROM users a
INNER JOIN events b
ON a.id = b.userid
WHERE now() > b.date
GROUP BY a.id,
a.name
ORDER BY max(b.date) DESC,
a.id DESC
LIMIT 30;
DISTINCT won't help you, when there are different date values for a user. Those records are distinct because of the different date values, though sharing a user.

Related

SQL query to compare 2 columns

I have a table that has 3 columns id, visit date and appointment date.
I want to write a sql query to find the following
For each id, how many entries are there where visit date matches with appointment date. Please note that the comparison has to happen across multiple rows for each id.
Example:
id Visit-date Appointment-date
1 20-1-2016 20-2-2016
1 20-2-2016 30-3-2016
1 04-04-2016 05-05-2016
and so on
Thanks a lot for the help.
Prasad
You can use a left join with aggregation to get the desired results:
select a.id,
count(b.appointment_date) as count
from your_table a
left join your_table b on a.id = b.id
and a.visit_date = b.appointment_date
group by a.id;
You can count records grouping by id.
select id, count(*) num_records
from your_table
where visit_date = appointment_date
group by id

SQL - selecting userid which has max number of not null rows in a different table

I've 3 tables say A,B,C.
Table A has userid column.
Table B has caid column.
Table C has lisid and image columns.
one userid can have one or several caids.
one caid can have one or several lisids.
how do I select a userid which has maximum number of rows with image column as not null (in some lisids image column is blank and in some it has some value).
can someone please help.
Presumably, the ids are spread among the tables in a reasonable fashion. If so, the following should do this:
select b.userid, count(*)
from TableB b join
TableC c
on b.caid = c.caid
where c.image is not null
group by b.userid
order by count(*) desc
limit 1
The question in the comments is how you connect TableA to TableB and TableB to TableC. The reasonable approach is to have the userid in TableB and the caid in TableC.
Getting all the rows with the max requires a bit more work. Essentially, you have to join in the above query to get the list
select s.*
from (select b.userid, count(*) as cnt
from TableB b join
TableC c
on b.caid = c.caid
) s
(select count(*) as maxcnt
from TableB b join
TableC c
on b.caid = c.caid
group by b.userid
order by count(*) desc
limit 1
) smax
on s.cnt = smax.cnt
Other databses have a set of functions called window functions/ranking functions that make this sort of query much simpler. Alas, MySQL does not offer these.

can this sql query be simplified?

I have 2 tables. MySql
users : A_ID,name
event : B_ID, A_ID,cat_id,date
Now I want to get all users , who participated more at events on a given period of time, and need to add based on category too. I am doing something like this :
select name from users ,
(select A_id, count(*)
from event
where date<=givendate
group by A_id
order by count(*) desc ) e
where users.A_id=e.a_id
limit 0,5
Is there any easy and prof way to write that script ?
Thanks
Your query looks OK apart from a few minor points:
Your ORDER BY and LIMIT should be in the outer select otherwise the order of the results is indeterminate.
Use the JOIN keyword to join two tables.
Try this:
SELECT u.name
FROM users AS u
JOIN
(
SELECT A_id, COUNT(*) AS cnt
FROM event
WHERE date <= givendate
AND cat_id = 42
GROUP BY A_id
) AS e
USING (A_id)
ORDER BY e.cnt DESC
LIMIT 5

sql pulling from sub query

Is it possible to pull 2 results from a sub query in a sql statement?
I have:
"SELECT
(SELECT bid FROM auction_bids WHERE itemID=a.id ORDER BY bid DESC LIMIT 1) as topbid,
a.* FROM auction_items a ORDER BY a.date DESC LIMIT 15"
The part where it returns the topbid, i'd also like it to pull not only bid (as topbid) but also date (as topdate) as well. How can I do that? Do I need another sub query or can it pull both in one?
Dependent subquery (depending on some values outside, like a.id in your case) is not a very efficient way to find maximum values in subsets.
Instead use a subquery with GROUP BY:
SELECT b.topbid, b.topdate, a.*
FROM auction_items a
LEFT JOIN
( SELECT itemID, MAX(bid) as topbid, MAX(date) as topdate
FROM auction_bids
GROUP BY itemID ) b
ON a.id = b.itemID
ORDER BY a.date DESC
LIMIT 15

Help with a MySql Query - The Rows Holding the Group-wise Maximum of a Certain Column

I need help returning a relevant result for this query. I have one table that I am hitting with three columns. trans_date, trans_amount and user_id
what I am trying to determine is this. For a given user_id when was the last trans_date and what was the trans_amount.
I'm having trouble returning the correct transaction_amount. Here is my code so far. It's returning the correct date but the amount is not right
select user_id, trans_date, trans_credit
from table
WHERE trans_credit =
(select max(trans_date) from inclick_account_act as f
where f.user_id = table.user_id);
Thanks in advance
If I understand you correctly you just want to get the most recent transaction for all users.
SELECT user_id, trans_date, trans_credit
FROM `table`
GROUP BY user_id
ORDER BY trans_date DESC;
How about something like
SELECT t.*
FROM table t INNER JOIN
(
SELECT user_id,
MAX(trans_date) max_trans_date
FROM table
GROUP BY user_id
) MaxDates ON t.user_id = MaxDates.max_trans_date