mysql 求一条 SQL 写法

2019-07-15 18:31:50 +08:00
 JasonTsang

用户表 1 user 用户登录日志表 2 user_login_log

两表通过 member_id 关联

现在 user_login_log 左连接到 user 表中 ( LEFT   JOIN )

select * from user left join user_login_log on user.id=user_login_log.member_id

...

问题来了,如何通过联表 如何查询 没有登录过的用户?就是说 查询 user_login_log 表中没有登录日志的用户。

我试过

select * from user left join user_login_log on user.id=user_login_log.member_id where user_login_log.member_id is null 不行

select * from user left join user_login_log on user.id=user_login_log.member_id where user_login_log.member_id="" 也不行

5831 次点击
所在节点    MySQL
20 条回复
FleyX
2019-07-15 18:45:35 +08:00
可以用子查询来解决。类似这样的写法:select * from ( selec * from a left join b on a.id = b.aId )a where a.bId is null

但是:非常不推荐这么写,效率太低了,数据量一大就会慢的怀疑人生。
建议这么来实现这个功能:用户表新增一个字段,记录用户上次登录时间。这样就能方便快捷的进行各种查询。
zpaopao
2019-07-15 18:54:29 +08:00
SELECT * FROM USER a
WHERE NOT EXISTS (SELECT * FROM user_login_log b on a.id=b.member_id)
zpaopao
2019-07-15 19:02:06 +08:00
我也不知道我的对不对,你可以试试。。。
JasonTsang
2019-07-15 19:03:12 +08:00
@zpaopao 一定要嵌套么?因为框架 无法使用嵌套
@FleyX 框架不能嵌套 SQL 有没有别的方法 就在 where 后加条件?
lanterboy
2019-07-15 19:12:11 +08:00
2L 正解
lanterboy
2019-07-15 19:13:47 +08:00
select * from user a
where not exists (select 1 from user_login_log b where a.id=b.member_id)
2L 把 where 打成 on 了
starsriver
2019-07-15 19:14:34 +08:00
这么写业务容易出问题
NullErro
2019-07-15 19:54:17 +08:00
我想知道 left outer join 为啥不行????
user 表结构:
+---------+-----------+
| user_id | user_name |
+---------+-----------+
| 1 | a |
| 2 | b |
| 3 | c |
+---------+-----------+
login_log 表:
+-----------+-------+
| member_id | other |
+-----------+-------+
| 2 | te |
+-----------+-------+
mysql> select a.user_id, a.user_name
-> from
-> (select user_id, user_name from tmp_user_0715)a
-> left outer join
-> (select member_id from tmp_user_login_log_0715)b
-> on a.user_id=b.member_id
-> where b.member_id is null;
+---------+-----------+
| user_id | user_name |
+---------+-----------+
| 1 | a |
| 3 | c |
+---------+-----------+
2 rows in set (0.01 sec)

完全可以啊
lolizeppelin
2019-07-15 20:08:57 +08:00
连登陆日志表,用户量大等死吧 233
你以为你是 pg 啊
ma836323493
2019-07-15 23:00:57 +08:00
建议楼主先去了解了解 left join 和 join 的用法
@zpaopao not exits 和 这个 哪个好 呢 select * from user join user_login_log on user.id=user_login_log.member_id where user_login_log.member_id is null
zpaopao
2019-07-16 09:01:31 +08:00
@ma836323493

个人意见:楼主的写法是错误的,在 LEFT JOIN 或者 JOIN 的时候,下面的 WHERE 语句,只是对原始数据表 user_login_log 的进行条件判定,而不是对笛卡尔积,在本身的错误的情况下,且如果 user_login_log 的 MEMBER_ID 是 PRIMARY KEY,是不会出现为空的子集。
zpaopao
2019-07-16 09:11:28 +08:00
如果楼主不想嵌套,

可以用 FULL OUTER JOIN
LeeSeoung
2019-07-16 09:45:04 +08:00
先把 left join 结果包一层 select,把 is null 的判断放这里试试。我印象中这样写是没问题的。
husky
2019-07-16 10:04:09 +08:00
一定要联表吗,分两次查?
fuxiuyin
2019-07-16 10:26:59 +08:00
select user.id, count(user_login_log.id) as count from user left join user_login_log on user.id=user_login_log.member_id group by id having count=0;
fuxiuyin
2019-07-16 10:27:50 +08:00
实验了一下,没错,这样可以,count user_login_log 表的任意字段就行。
fuxiuyin
2019-07-16 10:47:22 +08:00
并且这么做应该是比嵌套查询快的。SQL 是描述要什么的语法,字查询更像是程序那种命令式的语法,先做什么后做什么,这样的话数据库自己是没什么优化的余地的。
回复不支持 md,所以要好好看的话还是复制走吧,join 会用 index,字查询就是扫表。

https://paste.ubuntu.com/p/MsFyKXbrW3/
zpaopao
2019-07-16 12:55:47 +08:00
感觉自己说复杂了,不知道为什么发不出来,其实楼主用 LEFT JOIN 也可以,只是不能写 where member_id is null 应该写 where 登陆日期 is null .. (至少我在自己本地数据库创建了 2 个表试了下是没问题的)
zpaopao
2019-07-16 13:01:52 +08:00
初学 SQL 的我,感觉自己也混乱了。。。楼主都试试吧···
fuxiuyin
2019-08-04 18:12:11 +08:00
今天看自己的回复列表的时候突然看到这个,反应过来了,这个就是集合 A-集合 B
select * from user left join user_login_log on user.id=user_login_log.member_id where user_login_log.member_id is null;
应该是可以的,然后又试了一下,这个在 PostgreSQL 上是没问题的,MySQL 上有问题,是 MySQL 自己的问题,MySQL 的实现看上去不是完整的关系运算。
https://stackoverflow.com/questions/406294/left-join-vs-left-outer-join-in-sql-server
可以看一下第一个回答的图。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/583190

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX