Выберите три строки, две из которых (сгруппированные) уникальны, другие отфильтрованы по другому столбцу (SQL) - PullRequest
0 голосов
/ 15 сентября 2010

Прежде всего я использую Oracle 10g Express

Итак, я хочу выделить три столбца:

[имя_домена] [путь_индекса] [имя_коллекции]

Теперь есть два столбца, которые я хочу быть уникальными (как группа):

[имя_домена] [путь_индекса]

И затем я хочу выбрать строку, на которую будет нанесен удар, когда другой столбец [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] является самой последней.


Чтобы прояснить несколько вопросов, я мог видеть, как люди спрашивают:

Вам нужно уникальное значение имени_домена И ИДИНСТВЕННОЕ значение индекса_пути или уникальное сочетание двух?

уникальная комбинация двух.

То есть есть несколько строк с одинаковым [имя_домена] [путь_индекса]?

Да.


Это код, с которым я сейчас работаю, но он не совсем работает:

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 ]

2 голосов
/ 15 сентября 2010

Это может привести к дублированию в случае дублирования значений 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 голос
/ 15 сентября 2010

С версии 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 collection name», но вы хотите, чтобы оно показывало «f collection name»:

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.

С уважением, Роб.

0 голосов
/ 15 сентября 2010
select distinct domain_name, 
                index_path, 
                first(collection_name) over (partition by domain_name, index_path order by gen_timestamp desc) 
from Your_Table
...