2015-07-08 3 views
2

Что я хотел бы сделать, это выбрать одну запись за уникальную метку времени в пределах заданного диапазона дат из моей таблицы. Если для одной и той же временной метки существует несколько записей, я хочу получить максимальную ненулевую запись или возвращать только нулевые записи. Я просто хочу вернуть одну из этих записей с нулевым значением. Запрос я использую «почти» работы, которыйSQL Выберите запись с MAX ненулевым значением. Если в противном случае существует запись с нулевым значением

select timestamp, MAX(value) FROM myTable WHERE *conditions*... group by [timestamp] Order By [timestamp] ASC;

Это, очевидно, работает хорошо, пока возвращаемые записи не являются нулями и отрицательные числа, в этом случае она возвращает нулевой записи, так как это больше, чем отрицательные записи. В этом случае я хотел бы вернуть одну из записей отрицательного значения, а не нулевую запись. Если я пытаюсь решить, что, изменив где заявление

WHERE [Value] <> 0 

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

+0

Если вы только ожидали 1 запись назад ... почему заказ по timstamp вообще? Просто выберите timestamp, значение из таблицы, где * conditions * order by value desc limit 1' max value будет первой записью из-за 'order by value desc', а предел 1 обеспечит возврат только 1 записи. независимо от того, есть ли значение 0 или 1. теперь, если нет никакой записи вообще из-за «Где условия», это совсем другая история ... но вы говорите, что записи возвращаются ...Поскольку у вас теперь есть это, максимальное значение, которое вы возвращаете, может не иметь никакого отношения к отметке времени, указанной в нем рядом с ... – xQbert

+0

Я хочу только 1 запись за уникальную метку времени, но мой запрос может вернуть сотни уникальных записей с меткой времени. Например, когда я запрашиваю 90 дней из нашей ежедневной таблицы данных, я ожидаю получить 90 записей. –

ответ

0

Дайте это попробовать, измените @ValueCol на 1, 0, null работает нормально.

DECLARE @ValueCol INT 
SET @ValueCol = Null 

Select CASE WHEN MAX(CASE WHEN @ValueCol IS NULL THEN 1 ELSE 0 END) = 0 THEN MAX(@ValueCol) END 

так, чтобы ваш SQL выглядел как это из исходного сообщения.

select 
timestamp 
, CASE WHEN MAX(CASE WHEN value IS NULL THEN 1 ELSE 0 END) = 0 THEN MAX(value) END 
FROM myTable 
WHERE *conditions*... 
group by [timestamp] 
Order By [timestamp] ASC; 
+1

Спасибо, что это именно то, что мне было нужно, и очень короткое и простое! Я тестировал его в нашей базе данных, и он отлично работает при обработке ненулевых, нулевых и нулевых временных файлов. Я бы проголосовал за ваш ответ, но пока у меня не хватает очков. Я вернусь и голосую, когда я это сделаю. –

+0

Каждый раз, SQL - это забавная игра для меня, я люблю смотреть на все эти проблемы, когда я не работаю над своим собственным кодом. Как и вы, мне приходилось иметь дело с этой ситуацией раньше, и это была самая элегантная вещь, которую я мог придумать. Рад, что это сработало для вас! –

1

Что я хотел бы сделать, это выбрать максимальное ненулевое значение, в том, как вы описали:

SELECT timestamp, MAX(valueCol) AS maxValue 
FROM myTable 
WHERE valueCol <> 0 
GROUP BY timestamp; 

Затем вы можете использовать внешнее соединение, чтобы получить все метки времени, а также использовать функцию COALESCE() заменить значения, которые не были возвращены с 0:

SELECT m.timestamp, COALESCE(t.maxValue, 0) AS maxValue 
FROM myTable m 
LEFT JOIN(
    SELECT timestamp, MAX(valueCol) AS maxValue 
    FROM myTable 
    WHERE valueCol <> 0 
    GROUP BY timestamp) t ON t.timestamp = m.timestamp; 

EDIT: на основе ваших комментариев и редактирования на ваш вопрос вы можете разбить эту проблему следующим образом. Я написал запрос (см. Выше), чтобы получить максимальное ненулевое значение для каждой отметки времени. Я также могу написать запрос, чтобы получить временные метки, где максимальная/минимальная временная метка 0, как это:

SELECT id, 0 AS MaxVal 
FROM myTable 
GROUP BY id 
HAVING MAX(valueCol) = 0 AND MIN(valueCol) = 0; 

Оставшаяся группа будет иметь значение нуль. Для того, чтобы получить те, что я могу сделать то же самое внешнее соединение в моем предыдущем примере, но оставить свою функцию COALESCE(), так что нулевые значения остаются таковыми:

SELECT DISTINCT m.id, t.maxVal 
FROM myTable m 
LEFT JOIN(
    SELECT id, MAX(valueCol) AS maxVal 
    FROM myTable 
    WHERE valueCol <> 0 
    GROUP BY id 
    UNION ALL 
    SELECT id, 0 AS maxVal 
    FROM myTable 
    GROUP BY id 
    HAVING MIN(valueCol) = 0 AND MAX(valueCol) = 0) t ON t.id = m.id; 

Я добавил DISTINCT ключевое слово, чтобы вернуть уникальный идентификатор/MaxValue пар, потому что несколько строк будут возвращены иначе, так как идентификатор появляется несколько раз в одной таблице.

Я тестировал это в SQL Fiddle, и он отлично работал.

+0

Я уже пробовал это, но, возможно, мне нужно быть более конкретным в моем вопросе, на самом деле есть 3 типа записей, ноль, нуль и нуль. Я бы хотел вернуть ненулевой первый, если они существуют, тогда, если ненулевые не существуют, я хотел бы вернуть нулевую запись, тогда, если нулевая запись не существовала, но была сделана нулевая запись, я бы хотел верните нуль. В вашем ответе я верю, что нулевые записи также вернутся как ноль. –

+0

Я понимаю. Это возможно, интернет сегодня пятнистый, поэтому я буду редактировать, когда смогу. – AdamMc331

+0

Отлично! Спасибо. –

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