2015-04-27 2 views
1

Я не знаю, как понять это, но вот пример таблицы:Как анализировать временные метки и состояния? (Novice)

╔════════════╦════════╦═══════════╗ 
║ Company_ID ║ Status ║ Timestamp ║ 
╠════════════╬════════╬═══════════╣ 
║  1234 ║ Test ║ 4/1/15 ║ 
║  1234 ║ Live ║ 3/30/15 ║ 
║  3456 ║ Live ║ 1/30/15 ║ 
║  4567 ║ Test ║ 2/12/15 ║ 
║  3456 ║ Test ║ 4/15/15 ║ 
╚════════════╩════════╩═══════════╝ 

Я хочу, чтобы вытащить только самую последнюю метку времени, так что я просто хочу:

╔════════════╦════════╦═══════════╗ 
║ Company_ID ║ Status ║ Timestamp ║ 
╠════════════╬════════╬═══════════╣ 
║  1234 ║ Test ║ 4/1/15 ║ 
║  4567 ║ Test ║ 2/12/15 ║ 
║  3456 ║ Test ║ 4/15/15 ║ 
╚════════════╩════════╩═══════════╝ 

До сих пор я хочу попробовать это, но я боюсь, что он просто потянет самую большую метку времени, но не со связанным статусом. Это правильно?

select 
    company_id, 
    status, 
    max(timestamp) 
from 
    sample 
group by 1, 2 

EDIT: Это на Redshift (PostgreSQL).

+1

Какой базой данными является это? Неправильно ваш запрос не будет работать, потому что вы получите одинаковые результаты, так как статусы разные. Также ваш вопрос очень похож на этот: http://stackoverflow.com/questions/612231/how-can-i-select-rows-with-maxcolumn-value-distinct-by-another-column-in-sql – SLin

+0

Извини за это. Redshift на PostgreSQL. Некоторые функции окна/раздела не работают в Redshift по какой-то причине, но ответы ниже были полезны! – JustCasual

+0

@JustCasual, если ответы ниже были вам полезны, вы можете проголосовать за них :-) – PhillipD

ответ

0

Это должно работать в любой современной СУБД .. Я проверил в в Oracle .. но должен работать в SQL * Server и т.д.

with w_data as (
     select 1234 company_id, 'Test' status, to_date('01-apr-2015','dd-mon-yyyy') ctime from dual union all 
     select 1234 company_id, 'Live' status, to_date('30-mar-2015','dd-mon-yyyy') ctime from dual union all 
     select 3456 company_id, 'Live' status, to_date('30-jan-2015','dd-mon-yyyy') ctime from dual union all 
     select 4567 company_id, 'Test' status, to_date('12-feb-2015','dd-mon-yyyy') ctime from dual union all 
     select 3456 company_id, 'Test' status, to_date('15-apr-2015','dd-mon-yyyy') ctime from dual 
     ), 
    w_sub as (
     select company_id, status, ctime, 
       row_number() over (partition by company_id order by ctime desc) rnum 
      from w_data 
     ) 
    Select company_id, status, ctime 
    from w_sub 
    where rnum = 1 
/

Результаты:

COMPANY_ID STAT CTIME 
    ---------- ---- -------------------- 
     1234 Test 01-apr-2015 00:00:00 
     3456 Test 15-apr-2015 00:00:00 
     4567 Test 12-feb-2015 00:00:00 

    3 rows selected. 
0

Попробуйте это:

select 
s1.company_id, 
s1.status, 
s1.timestamp 
from 
sample s1 
JOIN (
SELECT company_id, max(timestamp) as timestamp 
FROM sample 
GROUP BY company_id) s2 
ON s1.company_id = s2.company_id 
    AND s1.timestamp= s2.timestamp 
0

Если ваш RDMS поддерживает аналитические функции (например, Oracle, Postgres, Vertica, ...), вы можете использовать что-то вроде:

select company_id, status, timestamp from (
    select 
    company_id, 
    status, 
    timestamp, 
    row_number() over (partition by company_id order by timestamp desc) as 'n' 
    from 
    sample 
) a where n = 1 

Аналитическая функция row_number() нумерует строку компания Мудрого относительно метки времени (в порядке в этом случае убывания), т.е. «новой» метки времени получает 1. Затем мы используем внешний запрос и получать только те строки, где row_number является 1.

Если вы используете MYSQL вы можете использовать функцию GROUP_CONCAT() в сочетании с SUBSTRING_INDEX()

select company_id, 
substring_index(group_concat(status order by timestamp desc separator ','), ',', 1), 
substring_index(group_concat(timestamp order by timestamp desc separator ','), ',', 1) 
from sample 
group by company_id 

(Убедитесь, что ваш RDMS обрабатывает ваш формат даты правильно)

+0

Это было прекрасно! – JustCasual

0

Несколько проще запрос с использованием функции окна с первым/last_value:

SELECT 
company_id, 
last_value(status) OVER (partition by company_id ORDER BY timestamp), 
last_value(timestamp) OVER (partition by company_id ORDER BY timestamp) 
FROM sample 
Смежные вопросы