mysql中用distinct查询多条不重复记录值 group count

本文探讨了MySQL中去除重复记录的有效方法。通过使用group by语句,解决了仅利用distinct无法同时返回多个字段的问题,并给出了简洁的实现方案。

需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记 录的条数,而不是用它来返回不重记录的所有值。其原因是distinct只能返回它的目标字段,而无法返回其它字段,这个问题让我困扰了很久,用 distinct不能解决的话,我只有用二重循环查询来解决,而这样对于一个数据量非常大的站来说,无疑是会直接影响到效率的。所以我花了很多时间来研究 这个问题,网上也查不到解决方案,期间把容容拉来帮忙,结果是我们两人都郁闷了。。。。。。。。。

下面先来看看例子:

table
id name
1 a
2 b
3 c
4 c
5 b

库结构大概这样,这只是一个简单的例子,实际情况会复杂得多。

比如我想用一条语句查询得到name不重复的所有数据,那就必须使用distinct去掉多余的重复记录。

select distinct name from table
得到的结果是:

name
a
b
c

好像达到效果了,可是,我想要得到的是id值呢?改一下查询语句吧:

select distinct name, id from table

结果会是:

id name
1 a
2 b
3 c
4 c
5 b

distinct怎么没起作用?作用是起了的,不过他同时作用了两个字段,也就是必须得id与name都相同的才会被排除。。。。。。。

我们再改改查询语句:

select id, distinct name from table

很遗憾,除了错误信息你什么也得不到,distinct必须放在开头。难到不能把distinct放到where条件里?能,照样报错。。。。。。。

很麻烦吧?确实,费尽心思都没能解决这个问题。没办法,继续找人问。

拉住公司里一JAVA程序员,他给我演示了oracle里使用distinct之后,也没找到mysql里的解决方案,最后下班之前他建议我试试group by。

试了半天,也不行,最后在mysql手册里找到一个用法,用group_concat(distinct name)配合group by name实现了我所需要的功能,兴奋,天佑我也,赶快试试。

报错。。。。。。。。。。。。郁闷。。。。。。。连mysql手册也跟我过不去,先给了我希望,然后又把我推向失望,好狠哪。。。。

再仔细一查,group_concat函数是4.1支持,晕,我4.0的。没办法,升级,升完级一试,成功。。。。。。

终于搞定了,不过这样一来,又必须要求客户也升级了。

突然灵机一闪,既然可以使用group_concat函数,那其它函数能行吗?

赶紧用count函数一试,成功,我。。。。。。。想哭啊,费了这么多工夫。。。。。。。。原来就这么简单。。。。。。

现在将完整语句放出:

select *, count(distinct name) from table group by name

结果:

id name count(distinct name)
1 a 1
2 b 1
3 c 1

最后一项是多余的,不用管就行了,目的达到。。。。。

唉,原来mysql这么笨,轻轻一下就把他骗过去了,郁闷也就我吧(对了,还有容容那家伙),现在拿出来希望大家不要被这问题折腾。

哦,对,再顺便说一句,group by 必须放在 order by 和 limit之前,不然会报错,差不多了,发给容容放网站上去,我继续忙碌。。。。。。

-----------------------------------------------------------------------------------------


更郁闷的事情发生了,在准备提交时容容发现,有更简单的解决方法。。。。。。

select id, name from table group by name

看来对mysql的了解还是太肤浅了,不怕被笑话,发出来让大家别犯同样的错误。。。。。。

by 索尔

摘自:http://hi.baidu.com/buypro/blog/item/0a8f9c08c0f47d226a60fb54.html

<think>好的,我需要帮助用户解决如何在MySQL查询同时选修了1号课程和2号课程的学生学号。根据用户提供的引用内容,特别是引用[1],里面提到了能直接使用AND连接同一属性的,比如cno='002' AND cno='003',这样会导致矛盾,无法正确查询。所以必须采用子查询或集合运算的方法。 首先,用户的问题是关于同时选修两门课程的情况,这和引用[1]中的例子类似,只是课程号换成了1号和2号。引用[1]中的解决方案是使用嵌套的子查询,先找到选修其中一门课程的学生,再筛选出同时选修另一门的学生。具体来说,先选课程1的学生学号,然后在其中筛选出那些也在课程2中的学号。 另一个可能的方法是使用交集操作,但MySQL本身支持INTERSECT关键字,所以需要使用其他方式模拟。例如,通过两次内连接SC表,分别对应课程1和课程2,然后确保两个连接中的学号相同。或者使用IN子句结合两个子查询,每个子查询分别选择选修课程1和课程2的学生学号,然后取交集。 此外,引用[3]中提到使用关系代数表达式,可能涉及自连接或者计数的方法,比如统计每个学生选修的课程数,然后筛选出至少两门的,但这里需要的是特定的两门课程,所以可能需要更精确的条件。 现在需要综合考虑同的方法,并确保SQL语法正确。根据引用[1]的示例,使用嵌套子查询的方法是比较直接的。具体步骤可能如下: 1. 从SC表中筛选出选修课程1的学生学号。 2. 在这些学号中,进一步筛选出那些也选修了课程2的学生。 3. 使用IN子句将这两个条件结合起来。 另外,可能还可以使用自连接的方法,即同一个学生学号在SC表中存在两条记录,分别对应课程1和课程2。这样可以通过JOIN操作来实现。 需要验证这两种方法的正确性,并检查是否存在性能差异或其他注意事项。例如,子查询可能效率较低,而连接方法可能在处理大数据量时更高效。此外,还要注意去重,避免重复的学号出现。 最后,根据用户提供的引用内容,特别是引用[1]中的例子,正确的SQL应该类似于: SELECT DISTINCT sno FROM sc WHERE cno = '1' AND sno IN ( SELECT sno FROM sc WHERE cno = '2' ); 或者使用自连接: SELECT a.sno FROM sc a INNER JOIN sc b ON a.sno = b.sno WHERE a.cno = '1' AND b.cno = '2'; 这两种方法都能得到正确的结果,但需要根据实际情况选择。同时,用户可能需要学号的唯一性,因此使用DISTINCTGROUP BY可能有必要,过如果SC表中每个学生每门课程只出现一次,可能需要。 另外,引用[3]中的关系代数方法可能转换为SQL时,使用COUNT和HAVING子句,但这里需要特定的课程,所以可能需要结合条件过滤。例如: SELECT sno FROM sc WHERE cno IN ('1', '2') GROUP BY sno HAVING COUNT(DISTINCT cno) = 2; 这种方法更简洁,但需要确保每个课程只被计数一次,尤其是如果有重复选课的情况,使用DISTINCT cno是必要的。 综上,应该提供几种同的方法,并解释它们的原理,让用户可以根据具体情况选择最适合的解决方案。</think>### 解答:如何查询同时选修1号和2号课程的学生学号? #### 方法1:嵌套子查询(推荐) 通过嵌套子查询实现集合运算,逻辑清晰且符合标准SQL语法: ```sql SELECT DISTINCT sno FROM sc WHERE cno = '1' AND sno IN ( SELECT sno FROM sc WHERE cno = '2' ); ``` **原理**: 1. 外层查询筛选选修1号课程的学生学号 2. 子查询筛选选修2号课程的学生学号 3. `IN`操作符实现两个集合的交集运算[^1] #### 方法2:自连接查询 通过同一表的自连接实现多条件匹配: ```sql SELECT a.sno FROM sc a JOIN sc b ON a.sno = b.sno WHERE a.cno = '1' AND b.cno = '2'; ``` **优势**: - 利用索引可提升大表查询性能 - 直观表达"同时存在两条记录"的语义 #### 方法3:GROUP BY聚合 通过分组统计实现集合运算: ```sql SELECT sno FROM sc WHERE cno IN ('1','2') GROUP BY sno HAVING COUNT(DISTINCT cno) = 2; ``` **注意**: - 必须使用`DISTINCT cno`避免重复选课干扰计数 - 参数`2`对应需要匹配的课程数量[^3] 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值