SQL: SELECT DISTINCT
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
SELECT DISTINCT
语法有时可能用于删除重复项,以防您的模式未规范化。 例如,在日志表中,您可能想要查询不同的 IP 地址
SELECT DISTINCT ip FROM access_log
create.selectDistinct(ACCESS_LOG.IP).from(ACCESS_LOG).fetch();
这对于临时查询特别有用。
很多时候,在应用程序查询中删除此类重复项时,您需要添加聚合函数(例如,每个 IP 的日志条目数,每个 IP 的不同登录数等),因此您将使用GROUP BY,而不是DISTINCT 子句。
但是,请注意使用 DISTINCT
来删除您不完全确定为什么会发生的重复项,即通常在非常大型和复杂的查询中,并且很多时候在存在(INNER) JOIN 表达式时,实际上应该有SEMI JOIN 表达式。 例如,以下查询查找以字母 A
开头的书店中所有书籍的作者
SELECT DISTINCT author.first_name, author.last_name FROM author JOIN book ON author.id = book.author_id JOIN book_to_book_store ON book.id = book_to_book_store.book_id WHERE book_to_book_store.name LIKE 'A%'
create.selectDistinct( AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .from(AUTHOR) .join(BOOK).on(AUTHOR.ID.eq(BOOK.AUTHOR_ID)) .join(BOOK_TO_BOOK_STORE) .on(BOOK.ID.eq(BOOK_TO_BOOK_STORE.BOOK_ID)) .where(BOOK_TO_BOOK_STORE.NAME.like("A%")).fetch();
现在,由于我们模式的性质
- 作者写了很多书
- 书籍在多个书店有售
因此,同一个作者很可能在结果中多次出现,因此使用 DISTINCT
。 从数据库性能的角度来看,这可能非常糟糕,因为作者在从结果中再次删除之前会被复制到一些内部数据结构中。 此外,根据优化器,即使我们已经找到作者,我们也可能必须扫描所有书籍和所有书店。 优化器非常不同,因此这在每个 RDBMS 中可能或可能不是严重程度相同的问题,但肯定需要注意。
SELECT author.first_name, author.last_name FROM author WHERE author.id IN ( SELECT book.author_id FROM book JOIN book_to_book_store ON book.id = book_to_book_store.book_id WHERE book_to_book_store.name LIKE 'A%' )
create.select( AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) .from(AUTHOR) .where(AUTHOR.ID).in( select(BOOK.AUTHOR_ID) .from(BOOK) .join(BOOK_TO_BOOK_STORE) .on(BOOK.ID.eq(BOOK_TO_BOOK_STORE.BOOK_ID)) .where(BOOK_TO_BOOK_STORE.NAME.like("A%") ).fetch();
现在,我们永远不会得到任何重复的作者。
如果有疑问,请检查您的执行计划和执行指标,了解这里最好的查询是什么,但在很多情况下,DISTINCT
提示正在进行一些不必要的操作,然后再次删除重复项。
反馈
您对此页面有任何反馈吗? 我们很乐意听取您的意见!