【问题标题】:Oracle SQL, how to select * having distinct columnsOracle SQL,如何选择 * 具有不同的列
【发布时间】:2018-04-05 09:06:41
【问题描述】:

我想要这样的查询(这不起作用!)

select * from foo where rownum < 10 having distinct bar

意思是我想从十个随机行中选择所有列,在列栏中具有 distinct 值。如何在 Oracle 中做到这一点?

这是一个例子。我有以下数据

| item    | rate |
-------------------
| a       | 50   |
| a       | 12   |
| a       | 26   |
| b       | 12   |
| b       | 15   |
| b       | 45   |
| b       | 10   |
| c       | 5    |
| c       | 15   |

结果例如

| item no | rate |
------------------
| a       | 12 |  --from (26 , 12 , 50)
| b       | 45 | --from (12 ,15 , 45 , 10)
| c       | 5  | --from (5 , 15)

没有不同的项目编号

【问题讨论】:

  • 添加一些示例表数据和预期结果。 (格式化文本,而不是图像。)
  • 您可以调整来自stackoverflow.com/q/41477607/330315 的答案。特别是stackoverflow.com/a/41477646/330315 只需删除order by newid()part
  • DISTINCT 始终适用于整行,否则没有意义。如果您只想获得item 的每个值,您可以使用GROUP BY item 并生成一个规则,该规则为item 的每个值选择rate 的可能值中的一个值。但是,GROUP BY` 不会将表中的完整行放入结果集中;它生成放入其结果集中的行。
  • 您的所有价格在项目组中都是不同的。例如,a 组中的 12 有何不同?我想你需要澄清一下。

标签: sql oracle oracle12c


【解决方案1】:

SQL Fiddle

Oracle 11g R2 架构设置

生成一个包含 12 个项目的表 A - L,每个项目的费率 0 - 4

CREATE TABLE items ( item, rate ) AS
SELECT CHR( 64 + CEIL( LEVEL / 5 ) ),
       MOD( LEVEL - 1, 5 )
FROM   DUAL
CONNECT BY LEVEL <= 60;

查询 1

SELECT item,
       rate
FROM   (
  SELECT i.*,
         -- Give the rates for each item a unique index assigned in a random order
         ROW_NUMBER() OVER ( PARTITION BY item ORDER BY DBMS_RANDOM.VALUE ) AS rn
  FROM   items i
  ORDER BY DBMS_RANDOM.VALUE -- Order all the rows randomly
)
WHERE  rn = 1                -- Only get the first row for each item
AND    ROWNUM <= 10          -- Only get the first 10 items.

Results

| ITEM | RATE |
|------|------|
|    A |    0 |
|    K |    2 |
|    G |    4 |
|    C |    1 |
|    E |    0 |
|    H |    0 |
|    F |    2 |
|    D |    3 |
|    L |    4 |
|    I |    1 |

【讨论】:

  • 为什么Oracle没有提供简单的关键字来实现这么简单的查询
  • @Tuomas Toivonen:想想你如何称呼这个“简单的关键字”。 a_random_row_per_parameter1_limited_to_parameter2_random_result_rows(id,10)?
  • @Thorsten Kettner。我认为我在 OP 中描述的伪查询是对期望结果的非常简单的表达。内部实现可以任意复杂,如此处所示的工作示例。因此,Oracle(或 SQL 标准)没有理由不能为此提供简单的关键字。我理解 select 语句针对单行并且不保持它正在累积结果集的状态,但这并不意味着它不能完成。
【解决方案2】:

我提到表创建和查询不同的前 10 行; (Ref SqlFiddle)

create table foo(item varchar(20), rate int);

insert into foo values('a',50);
insert into foo values('a',12);
insert into foo values('a',26);
insert into foo values('b',12);
insert into foo values('b',15);
insert into foo values('b',45);
insert into foo values('b',10);
insert into foo values('c',5);
insert into foo values('c',15);

--这里首先获取不同的项目,然后过滤行数行:

 select item, rate from (
      select item, rate, ROW_NUMBER() over(PARTITION BY item ORDER BY rate desc) 
     row_num  from foo 
 )  where row_num=1;

【讨论】:

  • 这不会将输出限制为 10 行(如果有超过 10 个项目)并且输出是确定性的而不是随机的(作为 OP 的要求)。
猜你喜欢
  • 2022-11-29
  • 1970-01-01
  • 2013-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多