2013-10-10 3 views
1

Вот мой SQL Скрипки: http://sqlfiddle.com/#!2/90d45/3Сравните первый и последний SQL строки с одинаковым идентификатором

Таблица Схема:

CREATE TABLE domain_rankings (domain_id int, rank int, create_date datetime); 
INSERT INTO domain_rankings VALUES (1, 0, "2012-01-01"); 
INSERT INTO domain_rankings VALUES (1, 2, "2012-01-02"); 
INSERT INTO domain_rankings VALUES (1, 1, "2012-01-03"); 
INSERT INTO domain_rankings VALUES (2, 0, "2012-01-01"); 
INSERT INTO domain_rankings VALUES (2, 1, "2012-01-02"); 
INSERT INTO domain_rankings VALUES (2, 2, "2012-01-03"); 
INSERT INTO domain_rankings VALUES (3, 1, "2012-01-01"); 
INSERT INTO domain_rankings VALUES (4, 3, "2012-01-01"); 
INSERT INTO domain_rankings VALUES (4, 2, "2012-01-02"); 
INSERT INTO domain_rankings VALUES (4, 1, "2012-01-03"); 

Я хочу, чтобы получить количество из Domain_ID-х годов, которые идут в ранге сравнивая первую запись к последней записи (по дате).

В этом случае для подсчета всех рангов вверх должно быть 2 (domain_id: 1, 2).

domain_id 3 не должен включаться в счет, поскольку он имеет только одну запись. Поэтому, возможно, нужен подзапрос HAVING COUNT (*)> 1.

domain_id 4 также не должен включаться в счетчик, если я не отменил запрос и не хочу, чтобы ранги спускались.

Как мне решить проблему? Я знаю, что мне понадобятся подзапросы, но я понятия не имею, с чего начать. JSFiddle должен дать вам представление о том, где я застрял.

попытки - это возвращает строки, которые являются действительными, но не COUNT строк правильно:

SELECT domain_id, COUNT(DR.domain_id) 
FROM domain_rankings DR 
WHERE 
    (SELECT rank 
    FROM domain_rankings 
    WHERE domain_rankings.domain_id = DR.domain_id 
    ORDER BY create_date ASC LIMIT 1 
) > (
    SELECT rank 
    FROM domain_rankings 
    WHERE domain_rankings.domain_id = DR.domain_id 
    ORDER BY create_date DESC LIMIT 1 
) 
GROUP BY DR.domain_id 
HAVING count(*) > 1 

Окончательный ответ (медленнее из двух вариантов):

SELECT COUNT(a.domain_id) cnt 
FROM (
    SELECT domain_id,MIN(create_date) mind, MAX(create_date) maxd 
    FROM domain_rankings 
    GROUP BY domain_id 
    HAVING COUNT(*) > 1 
) master 
JOIN domain_rankings a 
    ON a.domain_id = master.domain_id 
AND a.create_date = master.mind 
JOIN domain_rankings b 
    ON b.domain_id = master.domain_id 
AND b.create_date = master.maxd 
WHERE a.rank < b.rank 
+0

Можете ли вы опубликовать ожидаемый результат таблицы? –

+0

Я думал, что сделал? Результат: Если я хочу, чтобы все разряды с ключевыми словами поднимались, результат должен быть равен 0. Если я хочу, чтобы все ранги с понижающимися ключевыми словами, результат должен быть равен 1. Мы игнорируем domain_id 3, потому что он имеет только одну строку , –

ответ

1

Может быть, не простейший подход, но вы можете, например, использовать подзапрос, чтобы получить минимальную и максимальную дату на домен domain_id и использовать регулярные соединения для получения соответствующих строк. Тогда вы можете просто сравнить ряды в конце;

SELECT COUNT(a.domain_id) cnt 
FROM (SELECT domain_id,MIN(create_date) mind, MAX(create_date) maxd 
     FROM domain_rankings GROUP BY domain_id) master 
JOIN domain_rankings a 
    ON a.domain_id = master.domain_id AND a.create_date = master.mind 
JOIN domain_rankings b 
    ON b.domain_id = master.domain_id AND b.create_date = master.maxd 
WHERE a.rank < b.rank 

Другой вариант заключается в использовании только ЛЕВЫЙ JOINS, чтобы отфильтровать первую и последнюю строку, и сравнить ряды;

SELECT COUNT(a.domain_id) cnt 
FROM domain_rankings a JOIN domain_rankings b 
    ON a.domain_id = b.domain_id AND a.rank < b.rank 
LEFT JOIN domain_rankings c 
    ON a.domain_id = c.domain_id AND a.create_date > c.create_date 
LEFT JOIN domain_rankings d 
    ON b.domain_id = d.domain_id AND b.create_date < d.create_date 
WHERE c.domain_id IS NULL and d.domain_id IS NULL; 

An SQLfiddle with both.

+0

Я изменил первый, чтобы иметь также HAVING COUNT (*)> 1 на master. Большое спасибо! –

0
SELECT count(*) 
FROM TABLE AS a 
INNER JOIN TABLE AS b ON a.domain_id=b.domain_id 
AND a.date=b.date-interval 2 DAY 
AND a.rank<b.rank 
+0

Подумайте о расширении своего ответа, чтобы объяснить, почему это достигает желаемого результата, возможно, связанного с документацией. Как есть, это лишь незначительно полезно. –

+0

Извините, но это слишком специфично для таблицы - если меняются даты, это не сработает с интервалом, к сожалению. –

Смежные вопросы