Oracle:DISTINCT或GROUP BY行一致性

时间:2013-12-04 10:05:17

标签: sql database oracle group-by distinct

我有以下表格:

Name  Parent  Status
A     P1      0
A     P2      1
B     PB      -1

以下队列保证,结果数据将与单行相关:

SELECT
  DISTINCT Name, Parent, Status
FROM
  MyTable

对于前。结果集可能包含:

A, P1, 1

它与表中的任何行都不匹配。如何编写一个SQL语句,用每个名称选择ANY和AT MOST ONE行?

2 个答案:

答案 0 :(得分:2)

SQL Fiddle

SELECT DISTINCT将获取每一行,然后丢弃结果集中的任何重复行。 您提供的数据在列中有重复但没有重复的行 - 因此将返回所有行:

查询1

SELECT DISTINCT
      Name,
      Parent,
      Status
FROM  MyTable

<强> Results

| NAME | PARENT | STATUS |
|------|--------|--------|
|    A |     P2 |      1 |
|    B |     PB |     -1 |
|    A |     P1 |      0 |
  

对于前。结果集可能包含:

A, P1, 1

不,你可以从上面的结果看出它没有。但是,您可以进行以下操作的查询:

查询2

SELECT Name,
       MIN( Parent ),
       MAX( Status )
FROM   MyTable
GROUP BY Name

<强> Results

| NAME | MIN(PARENT) | MAX(STATUS) |
|------|-------------|-------------|
|    A |          P1 |           1 |
|    B |          PB |          -1 |

回答你的最后一个问题:

  

如何编写一个SQL语句,用每个名称选择ANY和AT MOST ONE行?

此查询随机排序行,然后为每个名称选择(随机)第一行:

查询3

WITH Randomness AS (
  SELECT Name,
         Parent,
         Status,
         ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY SYS.DBMS_RANDOM.VALUE() ) AS Random_ID
  FROM   MyTable
)
SELECT Name,
       Parent,
       Status
FROM   Randomness
WHERE  Random_ID = 1

<强> Results

| NAME | PARENT | STATUS |
|------|--------|--------|
|    A |     P1 |      0 |
|    B |     PB |     -1 |

如果您再次运行查询3,那么您可能会返回另一个A行(或者不是 - 它是随机的)。

或者,如果您想要相当愚蠢且完全随机,那么您可以为每个名称选择随机父级和随机状态(这样父级和状态不必来自原始表的同一行)。

查询4

SELECT Name,
       MIN( Parent ) KEEP ( DENSE_RANK FIRST ORDER BY SYS.DBMS_RANDOM.VALUE() ) AS Random_Parent,
       MIN( Status ) KEEP ( DENSE_RANK FIRST ORDER BY SYS.DBMS_RANDOM.VALUE() ) AS Random_Status
FROM   MyTable
GROUP BY Name

<强> Results

| NAME | RANDOM_PARENT | RANDOM_STATUS |
|------|---------------|---------------|
|    A |            P1 |             1 |
|    B |            PB |            -1 |

答案 1 :(得分:1)

请尝试:

SELECT 
  Name, 
  Parent, 
  Status
FROM(
  select
    Name, 
    Parent, 
    Status,
    ROW_NUMBER() 
      OVER (PARTITION BY Name order by Status desc) RNum
  From YourTable
  )x where RNum=1

SQL Fiddle Demo