简体   繁体   中英

How to compare rows from same table in sql

My tables are:

frequents(bar,drinker);
likes(beer,drinker);
serves(bar,beer)

I want to "select pairs of drinkers who frequents exactly the same bars".I think I can write that query using only the frequents table (as it has both bar and drinker column) using self joints I tried to do but couldn't get it.I don't mind using other tables too to get the exact query.The query must select drinkers who goes to the same bars only.In other words they should have all the the bars in common.The query must be in generalized form it should not depend on data that's why I didn't put any data.

DRINKER |     BAR  
____________________    
John    |     Hyatt       
Smith   | Blue     
William | Hilton   
John    | Geoffreys 
Smith   | Hyatt     
Joe     | Blue      
Mike    | Hilton    
William | Dublin        
Jeff    | Hilton        
Jake    | Hilton    

This is my frequents table I need to select only Joe and Smith and also Jake and Jeff because they visit exactly the same bars.

THe easiest way in MySQL is to use group_concat() to put the values together and compare:

select fd.bars, group_concat(fd.drinker) as drinkers
from (select f.drinker, group_concat(f.bar order by f.bar) as bars
      from frequents f
      group by f.drinker
     ) fd
group by bars
having count(*) > 1;

EDIT

You can also do this using join s, but to do it right, you need a full outer join -- which MySQL does not support.

Another way is to count the number of bars that each goes to, do an inner join, and be sure that the counts match as well as the bars:

select f1.drinker, f2.drinker
from frequents f1 join
     frequents f2
     on f1.bar = f2.bar join
     (select f.drinker, count(*) as numbars
      from frequents f
      group by f.drinker
     ) fd1
     on f1.drinker = fd1.numbars join
     (select f.drinker, count(*) as numbars
      from frequents f
      group by f.drinker
     ) fd2
     on f2.drinker = f2.drinker
group by f1.drinker, f2.drinker
having count(*) = max(f1.numbars) and count(*) = max(f2.numbars);

This may help, however I'm using my knowledge from Microsoft SQL server. The syntax may differ from MYSQL. That being said you would need to JOIN the tables into themselves.

SELECT F.Bars, F.Drinkers, FB.Drinker 
FROM frequents F 
JOIN frequents FB ON (FB.Drinkers = F.Bars)
WHERE FB.Drinkers = F.Drinkers

basically I join the same table to itself saying the FB.Drinkers contains the bars that drinkers go to and F.Drinkers is the list of people who drink. I'm not 100% on the syntax but the idea is correct.

I haven't done SQL in 4 months. if you don't use it, you loose it :)

fixnode's answer is pretty good, although it lacks 2 little details that I think are important, select only non repeated results and sort them in a useful way.

SELECT DISTINCT tbl_1.drinker, tbl_1.bar
FROM `frequents` AS tbl_1
LEFT JOIN frequents AS tbl_2 ON tbl_1.bar = tbl_2.bar WHERE tbl_1.bar = tbl_2.bar
ORDER BY tbl_1.bar;

This is what I used for testing

CREATE TABLE IF NOT EXISTS `frequents` (
  `bar` varchar(100) NOT NULL,
  `drinker` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `frequents` (`bar`, `drinker`) VALUES
('bar_1', 'drinker_3'),
('bar_2', 'drinker_3'),
('bar_3', 'drinker_4'),
('bar_4', 'drinker_1'),
('bar_5', 'drinker_1'),
('bar_1', 'drinker_5'),
('bar_2', 'drinker_4'),
('bar_3', 'drinker_3'),
('bar_4', 'drinker_2'),
('bar_5', 'drinker_1');

Well you are not showing anyone desired output but if you add a table for the bar, then this will work for you

select f.bar, f.drinker from frequents f
inner join bar b on b.bar = f.bar

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM