sql面试题2,自连接,查找共同使用ip数目>=3的名单

1.拼多多面试题sql(来自牛客)

自连接的思路 t1 join t2 on t1.ip=t2.ip where t1.uid != t2.uid group by t1.uid, t2.uid having count(*)>=3,但是这样自连接不会出现id1,id2和id2,id1这样反序的重复情况,所以我就改成log1.uid那输出就是ba,否则会有ab ba两条。

select log1.uid,log2.uid

from ip_log log1 inner join ip_log log2 on log1.ip=log2.ip  and log1.uid

group by log1.uid,log2.uid

having count(*)>=3


建一个表看看,方便理解:

truncate table ip_log;

insert into ip_log values('a' , '124' , '2019-08-07');

insert into ip_log values('b' , '124' , '2019-08-07');

insert into ip_log values('c' , '124' , '2019-08-07');

insert into ip_log values('a' , '174' , '2019-08-07');

insert into ip_log values('b' , '174' , '2019-08-07');

insert into ip_log values('a' , '194' , '2019-08-07');

insert into ip_log values('b' , '124' , '2019-08-07');




2.

order(ord_id,mall_id,goods_id,sale_number,amount),求每个商店里的商品价格的中位数。

(用到了开窗函数和join,我大体方向正确,但是考虑不周全,面试官有引导纠正)


我觉得下面这类似的求的不是特别好

应该用 rank over 开窗排序



select *

from

(SELECT id,name, Sales,rank() over (partition by id order by Sales) rank_

FROM median_sale)a

inner join

(select id,count(*) as cnt from median_sale group by 1 )b

on a.id=b.id

where a.rank_=(b.cnt+1) div 2


增加考虑奇偶,如果是偶数保留中间两个,最后求平均


select a.id,avg(Sales) as median

from

(SELECT id,name, Sales,rank() over (partition by id order by Sales) rank_

FROM median_sale)a

inner join

(select id,count(*) as cnt from median_sale group by 1 )b

on a.id=b.id

where

case when b.cnt%2 !=0 then a.rank_=((b.cnt+1) div 2)

else (a.rank_= (b.cnt) div 2 or (a.rank_= b.cnt div 2 +1) )end

group by 1



中间步骤是这样的



WHERE tab.sales_rank=(select (count(*)+1) div 2 from total_sales);


SELECT * from

(

SELECT a1.Name, a1.Sales, COUNT(a2.sales) Sales_Rank

FROM Total_Sales a1, Total_Sales a2

WHERE a1.Sales < a2.Sales or (a1.Sales=a2.Sales and a1.Name = a2.Name)

GROUP BY a1.Name, a1.Sales

ORDER BY a1.Sales DESC, a1.Name DESC

) as tab WHERE tab.sales_rank=(select (count(*)+1) div 2 from total_sales);

可以查找到中间的项,count(*)+1,这个1必须要添加,总项数假如为奇数7,则count(*)+1 / 2 = 4,假如是6则为3,都是满足的,如果不+1的话,对奇数项则不满足,如7,count(*) /2 = 3,而我们要查找的则是位于4的位置




滴滴sql一

image.png

两个表如上,查出每个司机每天接的第一单(name,o_id);

方法一

image.png

方法二

image.png

存在问题:没有接单的用户不存在了

可以改进使用左连接和右连接

作者:微斯人_吾谁与归

链接:https://www.jianshu.com/p/eb4d8404ec12

来源:

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。






insert into t1 values('1','c罗','33');

insert into t1 values('2','梅西','31');

insert into t1 values('3','内马尔','29');

insert into t2 values('1','3','1');

insert into t2 values('1','5','2');

insert into t2 values('2','0','1');

insert into t2 values('2','8','2');


很多同学在学习 Mysql 表关联的时候弄不清ON与WHERE的区别,不知道条件应该写在ON里面还是WHERE里面,作者在工作的时候也入过坑,总觉得条件写在哪里查询结果都是一样的,最后出错坏了事,差点惹了大祸。所以今天简单易懂的总结一下他们的区别,大家共同学习。

准备工作

我们先准备两个表,并造一些数据:

-- t1createtablet1(idbigintdefault'0'notnullcomment'主键id',namechar(100)default''notnullcomment'姓名',ageintdefault'0'notnull);-- t2createtablet2(idbigintdefault'0'notnullcomment'主键id',goalsintdefault'0'notnullcomment'进球数',matchesintdefault'0'notnullcomment'比赛编号');

t1, t2

探究

口诀:先执行ON,后执行WHERE;ON是建立关联关系,WHERE是对关联关系的筛选。记住这句话就可以准确地判断查询结果了,我们通过两个 sql 来进行分析:

SELECTt1.id,t1.name,t1.ageFROMt1LEFTJOINt2ONt1.id=t2.idWHEREmatches=2;-- 条件放在 WHERESELECTt1.id,t1.name,t1.ageFROMt1LEFTJOINt2ONt1.id=t2.idANDmatches=2;-- 条件放在 ON

执行第一个 sql 时,前提是LEFT JOIN,所以左边的数据在创建关联关系时会保留,根据口诀,先执行ON建立关联关系,然后通过WHERE筛选,过程如下:

sql1

第二个 sql 没有WHERE,那么ON建立的关联关系就是最终结果:

sql2

通过这两个 sql 可以很好的区分WHERE和ON的区别了,希望大家使用的时候多注意这一点,避免犯错!

作者 小菜荔枝原创 转载请联系作者获得授

作者:小菜荔枝

链接:https://www.jianshu.com/p/d923cf8ae25f

来源:

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


在使用left join时,on and和 where and条件的区别如下:

 在使用链接时,先执行 on and,再执行  where and

1. on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左表中的记录。

2. where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录了),

    条件不为真的就全部过滤,on后的条件用来生成左右表关联的临时表,where后的条件对临时表中的记录进行过滤。


在使用inner join时,on and和 where and条件:

取交集,on and后对左右表都筛选,和where一样。


具体数据比较看原链接:

http://blog.csdn.net/xingzhemoluo/article/details/39677891

你可能感兴趣的:(sql面试题2,自连接,查找共同使用ip数目>=3的名单)