选择三行,其中两行(分组)唯一,其他由另一列过滤(SQL)

时间:2010-09-14 20:52:26

标签: sql oracle plsql oracle10g aggregate-functions

首先我使用的是Oracle 10g Express

所以我想选择三列:

[domain_name] [index_path] [collection_name]

现在有两列我想要独特(作为一个组):

[domain_name] [index_path]

然后我想在另一列[gen_timestamp]最近的时候选择保留的行。

所以我的问题是基本上如何:

SELECT domain_name, index_path, MIN(collection_name) collection_name
FROM TABLENAMEHERE
GROUP BY domain_name, index_path;

但不是选择min collection_name,而是选择[gen_timestamp]是最新的行。


为了澄清一些我可以看到人们问的问题:

您是否需要domain_name的唯一值,以及index_path的唯一值,或者两者的唯一COMBINATION?

两者的独特组合。

那么[domain_name] [index_path]有多行?


这是我现在正在使用的代码,但它不能正常工作:

select domain_name, index_path, collection_name
  from my_table outr
       inner join 
         (select domain_name, index_path, collection_name, 
                 max(gen_timestamp) 
                    over (partition by domain_name, index_path) gen_timestamp
            from my_table) innr
 where outr.domain_name = innr.domain_name
   and outr.index_path  = innr.index_path
   and outr.collection_name = innr.collection_name
   and outr.gen_timestamp   = innr.gen_timestamp

3 个答案:

答案 0 :(得分:2)

如果出现重复的gen_timestamp值,则存在重复:

 SELECT x.domain_name, 
        x.index_path, 
        x.collection_name
   FROM TABLENAMEHERE x
   JOIN (SELECT t.domain_name,
                t.index_path,
                MAX(t.gen_timestamp) AS max_ts
           FROM YOUR_TABLE t
       GROUP BY t.domain_name, t.index_path) y ON y.domain_name = x.domain_name
                                              AND y.index_path = x.index_path
                                              AND y.max_ts = x.gen_timestamp
ORDER BY domain_name, index_path

使用ROW_NUMBER(9i +),没有重复的风险:

WITH summary AS (
  SELECT t.domain_name,
         t.index_path,
         t.collection_name,
         ROW_NUMBER() OVER(PARTITION BY t.domain_name,
                                        t.index_path
                               ORDER BY t.gen_timestamp DESC) AS rank
    FROM YOUR_TABLE t)
  SELECT s.domain_name,
         s.index_path,
         s.collection_name
    FROM summary s
   WHERE s.rank = 1
ORDER BY domain_name, index_path

答案 1 :(得分:1)

从版本9开始,有一个聚合函数可以完全满足您的要求。不幸的是,我还没有在你的两个主题的回答中看到过这个。

用于演示您的问题的表格:

SQL> create table tablenamehere (domain_name,index_path,collection_name,gen_timestamp)
  2  as
  3  select 'A', 'Z', 'a collection name', systimestamp from dual union all
  4  select 'A', 'Z', 'b collection name', systimestamp - 1 from dual union all
  5  select 'A', 'Y', 'c collection name', systimestamp from dual union all
  6  select 'B', 'X', 'd collection name', systimestamp - 2 from dual union all
  7  select 'B', 'X', 'e collection name', systimestamp - 4 from dual union all
  8  select 'B', 'X', 'f collection name', systimestamp from dual
  9  /

Table created.

显示min(collection_name)的查询。这显示“d集合名称”,但您希望它显示“f集合名称”:

SQL> SELECT domain_name, index_path, MIN(collection_name) collection_name
  2  FROM TABLENAMEHERE
  3  GROUP BY domain_name, index_path
  4  /

D I COLLECTION_NAME
- - -----------------
A Y c collection name
A Z a collection name
B X d collection name

3 rows selected.

无需对所有行应用分析函数并对这些结果进行过滤:您正在进行聚合,而LAST函数可以完全完成您的工作。以下是文档的链接:http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions071.htm#sthref1495

SQL> select domain_name
  2       , index_path
  3       , max(collection_name) keep (dense_rank last order by gen_timestamp) collection_name
  4    from tablenamehere
  5   group by domain_name
  6       , index_path
  7  /

D I COLLECTION_NAME
- - -----------------
A Y c collection name
A Z a collection name
B X f collection name

3 rows selected.

此致 罗布。

答案 2 :(得分:0)

select distinct domain_name, 
                index_path, 
                first(collection_name) over (partition by domain_name, index_path order by gen_timestamp desc) 
from Your_Table