select 中的DISTINCT用法

MySQL DISTINCT用法
本文探讨了MySQL中DISTINCT关键字的使用技巧,特别是如何利用COUNT(DISTINCT field)结合GROUP BY来实现查询字段不重复记录的需求。
2007-10-31 17:18
select 中的DISTINCT用法

在 使用mysql时,有时需要查询出某个字段不重复的记录,虽然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 DISTINCT` 的方法 在 Oracle 中,`SELECT DISTINCT` 用于去除重复的行,确保查询结果中每行数据都是唯一的。该子句只能在 `SELECT` 语句中使用,并且在 `SELECT` 子句中指定的字段决定了哪些行被视为重复。例如,如果查询中包含多个字段,只有当所有字段的值组合相同,才会被视为重复记录 [^1]。 ```sql SELECT DISTINCT APPLYPERSON, DEMANDDEPT FROM GK_WZ_OUTORDER WHERE OPTDWID = '38'; ``` 上述查询将返回 `APPLYPERSON` 和 `DEMANDDEPT` 的唯一组合,适用于需要去除重复记录的场景。 ### 常见问题及解决方案 #### 1. `SELECT DISTINCT` 中无法显示额外字段 在使用 `SELECT DISTINCT` 时,不能在 `SELECT` 子句中包含未在 `DISTINCT` 中指定的字段。例如,若表中存在 `REMARK` 字段,而查询中仅对 `APPLYPERSON` 使用 `DISTINCT`,则无法直接显示 `REMARK` 字段的内容。这是因为 `DISTINCT` 仅作用于指定字段,而额外字段可能包含多个不同的值,导致数据库无法确定如何处理这些值 [^2]。 ```sql -- 错误示例 SELECT DISTINCT APPLYPERSON, REMARK FROM GK_WZ_OUTORDER WHERE OPTDWID = '38'; ``` 若确实需要显示额外字段,可以使用聚合函数(如 `MAX`、`MIN`)来处理这些字段,确保查询逻辑符合唯一性要求: ```sql SELECT APPLYPERSON, MAX(REMARK) AS REMARK FROM GK_WZ_OUTORDER WHERE OPTDWID = '38' GROUP BY APPLYPERSON; ``` #### 2. `SELECT DISTINCT` 与 `ORDER BY` 的兼容性 当 `SELECT` 子句中包含 `DISTINCT` 时,`ORDER BY` 子句中使用的字段必须在 `SELECT` 子句中出现。这是因为 `DISTINCT` 操作已经对数据进行了去重,数据库无法确保 `ORDER BY` 中未出现的字段仍然有效 [^4]。 ```sql -- 错误示例 SELECT DISTINCT APPLYPERSON FROM GK_WZ_OUTORDER ORDER BY DEMANDDEPT; ``` 为避免此问题,应确保 `ORDER BY` 中的字段在 `SELECT` 子句中出现: ```sql SELECT DISTINCT APPLYPERSON, DEMANDDEPT FROM GK_WZ_OUTORDER ORDER BY DEMANDDEPT; ``` #### 3. `SELECT DISTINCT` 与 `GROUP BY` 的性能差异 在某些情况下,`SELECT DISTINCT` 和 `GROUP BY` 的执行效率可能不同。尽管两者在逻辑上可能等效,但数据库的优化器可能选择不同的执行计划。例如,在一个复杂查询中,使用 `GROUP BY` 可能比 `SELECT DISTINCT` 更快,因为 `GROUP BY` 会自动对数据进行排序并生成哈希表,而 `SELECT DISTINCT` 仅进行去重操作 [^3]。 ```sql -- 使用 GROUP BY 提高性能 SELECT APPLYPERSON, DEMANDDEPT FROM GK_WZ_OUTORDER WHERE OPTDWID = '38' GROUP BY APPLYPERSON, DEMANDDEPT; ``` #### 4. 不使用 `DISTINCT` 实现去重效果 在 Oracle 中,除了 `SELECT DISTINCT` 外,还可以使用 `GROUP BY` 或聚合函数来实现去重效果。例如,使用 `GROUP BY` 可以达到与 `SELECT DISTINCT` 相同的结果,同时还可以进行额外的聚合操作,如 `COUNT`、`SUM` 等 [^5]。 ```sql SELECT APPLYPERSON, COUNT(*) AS DUPLICATE_COUNT FROM GK_WZ_OUTORDER WHERE OPTDWID = '38' GROUP BY APPLYPERSON; ``` 此查询不仅去除了重复的 `APPLYPERSON`,还统计了每个值的出现次数。 ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值