MySQL之——GROUP BY分组取字段最大值

转载自:http://blog.csdn.net/l1028386804/article/details/54657412

假设有一个业务场景,需要查询用户登录记录信息,其中表结构如下:

[sql] view plaincopy
  1. CREATE TABLE `tb` (  
  2.   `id` int(11) NOT NULL AUTO_INCREMENT,  
  3.   `uid` int(11) NOT NULL,  
  4.   `ip` varchar(16) NOT NULL,  
  5.   `login_time` datetime,  
  6.   PRIMARY KEY (`id`),  
  7.   KEY (`uid`)  
  8. );  

再来点测试数据:

[sql] view plaincopy
  1. INSERT INTO tb SELECT null, 1001, '192.168.1.1', '2017-01-21 16:30:47';  
  2. INSERT INTO tb SELECT null, 1003, '192.168.1.153', '2017-01-21 19:30:51';  
  3. INSERT INTO tb SELECT null, 1001, '192.168.1.61', '2017-01-21 16:50:41';  
  4. INSERT INTO tb SELECT null, 1002, '192.168.1.31', '2017-01-21 18:30:21';  
  5. INSERT INTO tb SELECT null, 1002, '192.168.1.66', '2017-01-21 19:12:32';  
  6. INSERT INTO tb SELECT null, 1001, '192.168.1.81', '2017-01-21 19:53:09';  
  7. INSERT INTO tb SELECT null, 1001, '192.168.1.231', '2017-01-21 19:55:34';  

表数据情况:

[plain] view plaincopy
  1. +----+------+---------------+---------------------+  
  2. | id | uid  | ip            | login_time          |  
  3. +----+------+---------------+---------------------+  
  4. | 1  | 1001 | 192.168.1.1   | 2017-01-21 16:30:47 |  
  5. | 2  | 1003 | 192.168.1.153 | 2017-01-21 19:30:51 |  
  6. | 3  | 1001 | 192.168.1.61  | 2017-01-21 16:50:41 |  
  7. | 4  | 1002 | 192.168.1.31  | 2017-01-21 18:30:21 |  
  8. | 5  | 1002 | 192.168.1.66  | 2017-01-21 19:12:32 |  
  9. | 6  | 1001 | 192.168.1.81  | 2017-01-21 19:53:09 |  
  10. | 7  | 1001 | 192.168.1.231 | 2017-01-21 19:55:34 |  
  11. +----+------+---------------+---------------------+  

如果只需要针对用户查出其最后登录的时间,可以简单写出:

[html] view plaincopy
  1. SELECT uid, max(login_time)  
  2. FROM tb  
  3. GROUP BY uid;  
[plain] view plaincopy
  1. +------+---------------------+  
  2. | uid  | max(login_time)       |  
  3. +------+---------------------+  
  4. | 1001 | 2017-01-21 19:55:34 |  
  5. | 1002 | 2017-01-21 19:12:32 |  
  6. | 1003 | 2017-01-21 19:30:51 |  
  7. +------+---------------------+  

若还需要查询用户最后登录时的其他信息,就不能用这种sql写了:

[sql] view plaincopy
  1. -- 错误写法  
  2. SELECT uid, ip, max(login_time)  
  3. FROM tb  
  4. GROUP BY uid;  
  5. -- 错误写法  

这样的语句是非SQL标准的,虽然能够在MySQL数据库中执行成功,但返回的却是未知的
(如果sql_mode开启了only_full_group_by,则不会执行成功。)
可能ip字段会取uid分组前的第一个row的值,显然不是所需信息
写法1
写一个子查询:

[sql] view plaincopy
  1. SELECT a.uid, a.ip, a.login_time  
  2. FROM tb a  
  3. WHERE a.login_time in (  
  4. SELECT max(login_time)  
  5. FROM tb  
  6. GROUP BY uid);  

写法2
再或者换一个写法:

[sql] view plaincopy
  1. SELECT a.uid, a.ip, a.login_time  
  2. FROM tb a  
  3. WHERE a.login_time = (  
  4. SELECT max(login_time)  
  5. FROM tb  
  6. WHERE a.uid = uid);  

顺便测了一下
在5.6以前的版本中,写法②这条sql在大数据量的情况下,执行计划不理想,目测性能不佳。
在5.6及以后的版本中,写法②这条sql会快很多,执行计划也有了改变
5.5.50:

[plain] view plaincopy
  1. +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+  
  2. | id | select_type        | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |  
  3. +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+  
  4. | 1  | PRIMARY            | a     | ALL  | NULL             | NULL  | NULL      | NULL | 7    | Using where |  
  5. | 2  | DEPENDENT SUBQUERY | tb    | ALL  | uid           | NULL  | NULL      | NULL | 7    | Using where |  
  6. +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+  

5.6.30:

[plain] view plaincopy
  1. +----+--------------------+-------+------+---------------+------+---------+------------+------+-------------+  
  2. | id | select_type        | table  | type | possible_keys | key  | key_len | ref       | rows  | Extra      |  
  3. +----+--------------------+-------+------+---------------+------+---------+------------+------+-------------+  
  4. | 1  | PRIMARY            | a     | ALL  | NULL              | NULL | NULL      | NULL        | 7    | Using where |  
  5. | 2  | DEPENDENT SUBQUERY | tb    | ref  | uid           | uid  | 4       | test.a.uid | 1    | NULL           |  
  6. +----+--------------------+-------+------+---------------+------+---------+------------+------+-------------+  

写法3
直接改成join性能会更加好:

[sql] view plaincopy
  1. SELECT a.uid, a.ip, a.login_time  
  2. FROM (SELECT uid, max(login_time) login_time  
  3. FROM tb  
  4. GROUP BY uid  
  5. ) b JOIN tb a ON a.uid = b.uid AND a.login_time = b.login_time;  

当然,结果都相同:

[plain] view plaincopy
    1. +------+---------------+---------------------+  
    2. | uid  | ip            | login_time          |  
    3. +------+---------------+---------------------+  
    4. | 1003 | 192.168.1.153 | 2017-01-21 19:30:51 |  
    5. | 1002 | 192.168.1.66  | 2017-01-21 19:12:32 |  
    6. | 1001 | 192.168.1.231 | 2017-01-21 19:55:34 |  
    7. +------+---------------+---------------------+ 

 

转载于:https://www.cnblogs.com/rainydayfmb/p/8371371.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/398768.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

王道操作系统考研笔记——2.1.4 进程通信

如果这篇博客对您有用的话,可以给我点个赞吗,这对我很重要,谢谢!❤️ 2.1.4 进程通信 知识总览 2.1.4.1 什么是进程通信 顾名思义,进程通信就是指进程之间的信息交换。 进程是分配系统资源的单位(包括内…

paper 35 :交叉验证(CrossValidation)方法思想

交叉验证(CrossValidation)方法思想简介以下简称交叉验证(Cross Validation)为CV.CV是用来验证分类器的性能一种统计分析方法,基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set),首先用训练集对分类器进行…

strerror和perror函数详解

/*#include <string.h> char *strerror(int errnum); 它返回errnum的值所对应的错误提示信息&#xff0c;例如errnum等于12的话&#xff0c;它就会返回"Cannot allocate memory"。 测试程序&#xff1a;*/ #include <stdio.h> #include <string.h>…

【2018-01-28】HTML-布局

位置&#xff1a; position&#xff1a;fixed 固定 absolute 绝对位置 relative 相对位置 top right     bottom left 流&#xff1a; float&#xff1a;left 向左流 right 向右流 both 清掉流 z-index分层&#xff1a; 值越大越靠上转载于:https://www.cnblogs.com/zqyyx…

关于设计模式——策略模式-Strategy Pattern

文章目录1 策略模式1.1 模拟鸭子1.2 设计原则1.3 整合行为1.4 模拟鸭子代码的代码1.5 动态设定行为1.6 重新查看整体1.7 继承和组合1.8 总结1.9 优劣期间应用场景2.0 参照资料1 策略模式 在我们什么都不会的情况下&#xff0c;我们先无需知道什么是策略模式&#xff0c;我们要…

python (3):wxPython打包app,报错

1&#xff0c;打包app报错 如图&#xff1a; 使用py2app&#xff0c;mac下打包成app。异常。程序直接退出。 没有详细的错误信息&#xff0c;client程序直接崩溃了。 2。原因 代码没有几行&#xff1a; #!/usr/bin/python # -*- coding: utf-8 -*- import wxapp wx.App(False…

.NET Framework 工具

您可以使用 .NET Framework 工具轻松创建、部署和管理面向 .NET Framework 的应用程序和组件。 此节中介绍的大部分 .NET Framework 工具将自动随 Visual Studio 一起安装。 &#xff08;有关安装信息&#xff0c;请参阅 Visual Studio 下载。&#xff09; 可以从命令行运行除程…

并发无锁队列学习(概念介绍)

1、前言 队列在计算机中很重要的一种数据结构&#xff0c;尤其在操作系统中。队列典型的特征是先进先出&#xff08;FIFO&#xff09;&#xff0c;符合流水线业务流程。在进程间通信、网络通信之间常常採用队列做缓存&#xff0c;缓解数据处理压力。结合自己在工作中遇到的队列…

王道操作系统考研笔记——2.1.5 线程概念与多线程模型

文章目录2.1.5 线程概念与多线程模型2.1.5.1 线程的来源2.1.5.2 线程机制带来的变化2.1.5.3 线程的属性2.1.5.4 线程的实现方式2.1.5.5 多线程模型2.1.5.6 小结2.1.5 线程概念与多线程模型 2.1.5.1 线程的来源 在很久以前还没有引入进程之前&#xff0c;系统中的各个程序只能…

mybatis处理集合、循环、数组和in等语句的使用

2019独角兽企业重金招聘Python工程师标准>>> 在Mybatis的xml配置中使用集合&#xff0c;主要是用到了foreach动态语句。 foreach的参数&#xff1a;foreach元素的属性主要有 item&#xff0c;index&#xff0c;collection&#xff0c;open&#xff0c;separator&…

#if defined 和 #if ! defined 的用法

背景&#xff1a;MFC初学&#xff0c;头文件中有#if !defined(AFX_HELLOMFC_H__706D36F5_2F1B_40AC_8BE9_0BD6A1D7BBDE__INCLUDED_)#define AFX_HELLOMFC_H__706D36F5_2F1B_40AC_8BE9_0BD6A1D7BBDE__INCLUDED_// Info : Other content #endif // !defined(AFX_HELLOMFC_H__706D…

Jmeter 通过Groovy保存数据到CSV

def outnew File("D:/pathdt.csv").append("\n"${__threadNum},${要导出的变量},) 转载于:https://www.cnblogs.com/Curious-wang/p/8378373.html

王道操作系统考研笔记——2.1.6 处理机调度的概念和层次

文章目录2.1.6 处理机调度的概念和层次2.1.6.1 调度的基本概念2.1.6.2 高级调度2.1.6.3 中级调度2.1.6.4 进程的挂起态和七状态模型2.1.6.5 低级调度2.1.6.6 三层调度的联系、对比2.1.6.7 小结2.1.6 处理机调度的概念和层次 知识总览 2.1.6.1 调度的基本概念 实际上&#xff…

CocoaPods详解之----使用篇

作者&#xff1a;wangzz 原文地址&#xff1a;http://blog.csdn.net/wzzvictory/article/details/18737437 转载请注明出处 如果觉得文章对你有所帮助&#xff0c;请通过留言或关注微信公众帐号wangzzstrive来支持我&#xff0c;谢谢&#xff01; 一、什么是CocoaPods 1、为什…

placeholder=请输入用户名(六位数字加英文字母)

placeholder"请输入用户名&#xff08;六位数字加英文字母&#xff09;" 转载于:https://www.cnblogs.com/nc-blog/p/4122768.html

文章集锦

不甘平庸的年轻人&#xff0c;全都有同一个特质&#xff1a;http://mp.weixin.qq.com/s/cQhS1nPxbsF3tini0-qvUA转载于:https://www.cnblogs.com/tianboblog/p/8383474.html

数据结构杂谈(五)——栈

本文的所有代码均由C编写 引用及参考资料&#xff1a; 王道数据结构大话数据结构超硬核十万字&#xff01;全网最全 数据结构 代码&#xff0c;随便秒杀老师/面试官&#xff0c;我说的_hebtu666-CSDN博客 5 栈 5.1 引入 在前面学习线性表的时候&#xff0c;我们给出了线性表的…

cocos3.2中如何创建一个场景

1.可以将一些比较通用的东西放到Common.h中,这是一个.h文件,必须手动添加,且保证在classes目录里 #ifndef __COMMON_H__ #define __COMMON_H__#include "cocos2d.h" USING_NS_CC;#define winSize Director::getInstance()->getWinSize() #define CCLog cocos2d::l…

每日一题——Leetcode203 移除链表元素

如果您是第一次看我写的博客&#xff0c;可以给我点个赞并关注我吗&#xff0c;我会持续分享更多有意思的干货。 文章目录1 题目2 思路3 代码4 小结1 题目 Leetcode203 移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val …

Linux入门之常用命令(15) lsof

查看磁盘空间&#xff1a; [rootticketb ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda1 981M 203M 729M 22% / none 16G 0 16G 0% /dev/shm /dev/sda9 2.9G 37M 2.7G 2% /tmp /dev/…