【问题标题】:Using distinct on a column and doing order by on another column gives an error在列上使用 distinct 并在另一列上执行 order by 会产生错误
【发布时间】:2012-01-18 06:01:20
【问题描述】:

我有一张桌子: abc_test 与列 n_num,k_str。

这个查询不起作用:

    select distinct(n_num) from abc_test order by(k_str)

但这一个有效:

    select n_num from abc_test order by(k_str)

DISTINCT 和 ORDER BY 关键字在两个查询的输出都发生变化时如何在内部工作?

【问题讨论】:

  • 如果你运行这两个查询,你能显示结果吗?第一个查询应返回错误ORA-01791: not a SELECTed expression,因为未选择k_str 列。这是您运行的实际查询吗? (在 9i 中可能可以接受,但我不能确定。)
  • 在 SQL Server 上的效果相同,但带有更具描述性的错误消息,“如果指定了 SELECT DISTINCT,则 ORDER BY 项必须出现在选择列表中。”

标签: sql oracle sql-order-by distinct oracle9i


【解决方案1】:

据我从你的问题中了解到。

distinct :- 表示选择一个不同的(所有选择的值都应该是唯一的)。 order By :- 仅表示根据您的要求对选定的行进行排序。

您的第一个查询中的问题是 例如 : 我有一张桌子

ID name
01 a
02 b
03 c
04 d 
04 a

现在查询select distinct(ID) from table order by (name) 混淆了它应该为ID - 04 记录哪个记录(因为那里有两个值,d 和a 在名称列中)。所以当你说数据库引擎的问题就在这里 按(姓名)排序…………

【讨论】:

    【解决方案2】:

    您可能会考虑使用 group by:

    select n_num
    from abc_test
    group by n_num
    order by min(k_str)
    

    【讨论】:

    • @FlorinGhita 你这是什么意思?我刚刚尝试了查询,对我来说它看起来很有效。
    • heeeei,您编辑了您的问题。 order by min(k_str)order by k_str 不同
    • @FlorinGhita 是的,我最初的回答中缺少 min(..) 部分。为此道歉。
    【解决方案3】:

    第一个查询是不可能的。 让我们通过例子来解释这一点。我们有这个测试:

    n_num k_str
    2     a
    2     c
    1     b
    

    select distinct (n_num) from abc_test

    2
    1
    

    Select n_num from abc_test order by k_str

    2
    1
    2
    

    你要返回什么

    select distinct (n_num) from abc_test order by k_str?

    应该只返回 1 和 2,但是如何排序呢?

    【讨论】:

    • 这个怎么样? select distinct (n_num) as iresult from abc_test ORDER BY iresult ASC
    • 当然他可以按第一栏排序。 OP 是关于为什么这个查询不起作用。你说的可以很简单:select distinct n_num from abc_test order by 1
    • "如何订购?" ——我能想到可能的办法:都是任意的;将明确的值按顺序排序,然后将不明确的值任意排序;等等。但我宁愿怀疑你的意思是我忽略了!
    • 如果n_num 的所有值在表中都不同,是否还会出现错误?如果是这样,这会改变你的结论吗?
    • 不难理解:对于 1 你有 b。对于 2,你有一个 c。哪个是第一? 1 还是 2? :)
    【解决方案4】:

    扩展键列如何排序

    第一个查询的logical order of operations in SQL 是(简化的):

    • FROM abc_test
    • SELECT n_num, k_str 即添加一个所谓的扩展排序键列
    • ORDER BY k_str DESC
    • SELECT n_num 即再次从结果中删除扩展排序键列

    感谢 SQL 标准的扩展排序键列 功能,可以按不在 SELECT 子句中的内容进行排序,因为它是在幕后临时添加的到订购,然后在订购后再次删除。

    那么,为什么这不适用于DISTINCT

    如果我们添加DISTINCT 操作,则需要在SELECTORDER BY 之间添加:

    • FROM abc_test
    • SELECT n_num, k_str 即添加一个所谓的扩展排序键列
    • DISTINCT
    • ORDER BY k_str DESC
    • SELECT n_num 即再次从结果中删除扩展排序键列

    但是现在,扩展排序键列 k_strDISTINCT 操作的语义已经改变,所以结果将不再相同。这不是我们想要的,因此 SQL 标准和所有合理的数据库都禁止这种用法。

    解决方法

    PostgreSQL 有 DISTINCT ON 语法,可以在这里使用它来完成这项工作:

    SELECT DISTINCT ON (k_str) n_num
    FROM abc_test
    ORDER BY k_str DESC
    

    如果您不使用 PostgreSQL,可以使用如下标准语法进行模拟

    SELECT n_num
    FROM (
      SELECT n_num, MIN(k_str) AS k_str
      FROM abc_test
      GROUP BY n_num
    ) t
    ORDER BY k_str
    

    或者,只是简单地(在这种情况下)

    SELECT n_num, MIN(k_str) AS k_str
    FROM abc_test
    GROUP BY n_num
    ORDER BY k_str
    

    I have blogged about SQL DISTINCT and ORDER BY more in detail here.

    【讨论】:

      【解决方案5】:

      您正在从查询的结果集中选择集合 distinct(n_num)。因此,与列 k_str 不再存在实际关系。 n_num 可以来自两行,每行都有不同的 k_str 值。因此,您不能按 k_str 对集合 distinct(n_num) 进行排序。

      【讨论】:

        【解决方案6】:

        根据 SQL 标准,SELECT 子句可以引用顶级 SELECT 子句中的子句(“别名”),也可以按序号位置引用结果集中的列,因此您的查询都不符合.

        似乎Oracle 与其他SQL 实现一样,允许您引用在SELECT 子句中被投影之前(逻辑上)存在的列。我不确定这种灵活性是否是一件好事:IMO 通过在SELECT 子句中包含列/表达式等来向调用应用程序公开排序顺序是一种很好的做法。

        与以往一样,您需要应用 dsicpline 才能获得有意义的结果。对于您的第一个查询,订单的定义可能完全是任意的。您应该感谢这个错误;)

        【讨论】:

          【解决方案7】:

          这种方法在 SQL server 2000 中可用,您可以从表中选择不同的值,并按不同的列排序,这不包含在 Distinct 中。 但在 SQL 2012 中,这会通过你一个错误 "如果指定了 SELECT DISTINCT,则 ORDER BY 项必须出现在选择列表中。"

          所以,如果您想使用与 SQL 2000 相同的功能,您仍然可以使用列号进行排序(在最佳实践中不推荐这样做)。

          select distinct(n_num) from abc_test order by 1
          

          这将在获取结果后对第一列进行排序。如果您希望排序应该基于不同的列而不是不同的,那么您必须在 select 语句中添加该列并使用列号进行排序。

          select distinct(n_num), k_str from abc_test order by 2
          

          【讨论】:

            【解决方案8】:

            当我遇到同样的错误时,我通过将其更改为解决它

            SELECT n_num 
            FROM(
               SELECT DISTINCT(n_num) AS n_num, k_str
               FROM abc_test
            ) as tbl
            ORDER BY tbl.k_str
            

            【讨论】:

            • 这不可能。你确定它不会导致重复吗?
            【解决方案9】:

            我的查询与您的不完全匹配,但非常接近。

            select distinct a.character_01 , (select top 1 b.sort_order from LookupData b where a.character_01 = b.character_01 )
            from LookupData a 
            where 
            Dataset_Name = 'Sample' and status = 200
            order by 2, 1
            

            【讨论】:

              【解决方案10】:

              你试过了吗?

              SELECT DISTINCT n_num as iResult
              FROM abc_test 
              ORDER BY iResult
              

              【讨论】:

              • 请参阅我的答案中的示例。您想返回什么查询?
              【解决方案11】:

              你可以的

              select distinct top 10000 (n_num)  --assuming you won't have more than 10,000 rows                
              from abc_test order by(k_str)
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-03-10
                • 1970-01-01
                • 2022-01-09
                • 1970-01-01
                • 2010-12-12
                • 1970-01-01
                • 2019-04-18
                • 1970-01-01
                相关资源
                最近更新 更多