Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL subquery - Find only first record in a LEFT JOIN

I'm trying to display a list of member records, and I have a few tables I'm using to display what I need.

That's the easy part. The part I need help with is with a table that has many records to each member record: Login history

I want to display only the first row for each member record, that exists in the Login History table. Alternatively, I may want to flip flop and display the last record in the Login History table, as well.

here's what I've got so far:

SELECT m.memberid, m.membername, m.gender, mp.phone
FROM tbl_members m, 
     tbl_members_phones mp, 
     tbl_members_addresses ma
WHERE m.defaultphoneid = mp.phoneid
AND m.defaultaddressid = ma.addressid

So that returns what's expected.

The 2 columns from tbl_members_login_history I'd like to add to the returned result are: mh.loggedtime, mh.ipaddy

I know adding the tbl_members_login_history as a LEFT JOIN would return duplicates, so I'm thinking there must be a Subquery necessity here, in order to return just the 1st record for that memberid that exists in tbl_members_login_history.

What I'm worried about is if no record in the history table exists, I still want to display that member info, but leave the history columns as NULL.

Would this be a subquery incident? and if so, how does one add that type of LIMIT?

like image 463
coffeemonitor Avatar asked Jan 23 '12 19:01

coffeemonitor


People also ask

Can we use subquery in left join?

A subquery can be used with JOIN operation. In the example below, the subquery actually returns a temporary table which is handled by database server in memory. The temporary table from the subquery is given an alias so that we can refer to it in the outer select statement.

IS LEFT join better than subquery?

A subquery is easier to write, but a joint might be better optimized by the server. For example a Left Outer join typically works faster because servers optimize it.

Does LEFT join return multiple rows?

Introduction to SQL Server LEFT JOIN clause The LEFT JOIN clause allows you to query data from multiple tables. The LEFT JOIN returns all rows from the left table and the matching rows from the right table. If no matching rows are found in the right table, NULL are used.


1 Answers

This is the greatest-n-per-group problem, which is asked frequently on Stack Overflow.

Here's how I would solve it in your scenario:

SELECT m.memberid, m.membername, m.gender, mp.phone, mh.loggedtime, mh.ipaddy
FROM tbl_members m 
INNER JOIN tbl_members_phones mp ON m.defaultphoneid = mp.phoneid
INNER JOIN tbl_members_addresses ma ON m.defaultaddressid = ma.addressid
LEFT OUTER JOIN tbl_members_login_history mh ON m.memberid = mh.memberid
LEFT OUTER JOIN tbl_members_login_history mh2 ON m.memberid = mh2.memberid
    AND mh.pk < mh2.pk
WHERE mh2.pk IS NULL;

That is, we want mh to be the most recent row in tbl_member_login_history for the given memberid. So we search for another row mh2 that is even more recent. If none more recent than the mh row is found, then mh2.* will be NULL, so mh must be the most recent.

I'm assuming this table has a primary key column that contains increasing values. For this example, I assume the column name is pk.

Using LEFT OUTER JOIN for both references to the login history table means that the m row will be reported even if there is no matching row.

like image 93
Bill Karwin Avatar answered Nov 07 '22 20:11

Bill Karwin