2014-08-28 7 views
-4

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

У меня около двух таблиц: tb_ticket и tb_updates.

Я создал SELECT с подзапросами, где потребовалось много времени (около 25 секунд), чтобы получить около 1000 строк. Теперь я изменил его на INNER JOIN, а не на многие SELECT s в подзапросах, это очень быстро (70 мс), но теперь я получаю дубликаты билетов. Я хотел бы знать, как я могу сделать, чтобы получить только последнюю строку (упорядочение по времени).

Мой текущий результат:

... 
67355;69759;"COMPANY X";"2014-08-22 09:40:21";"OPEN";"John";1 
67355;69771;"COMPANY X";"2014-08-26 10:40:21";"UPDATE";"John";1 

Первый столбец является билет ID, то второй является обновление ID ... Я хотел бы получить только строку за билет ID, но В этом случае DISTINCT не работает. Какая строка должна быть? Всегда последний, поэтому в этом случае 2014-08-26 10:40:21.

ОБНОВЛЕНИЕ: Это база данных postgresql. Я не передал свой текущий запрос, потому что у него есть только португальские имена, поэтому я думаю, что это не помогло бы вообще.

РЕШЕНИЕ: Used_By_Already было лучшее решение моей проблемы.

+3

Что такое СУБД? – Dimt

+3

Было бы блестящим, если бы вы могли дать нам инструкцию SQL для работы с – Marco

+0

. Ваши таблицы имеют префикс 'tb_'. Из интереса ваши хранимые процедуры префикс 'sp_'? –

ответ

3

Без подробностей ваших таблиц один должен угадать имена полей, но кажется, что tb_updates имеет много записей для одной записи в tb_ticket (отношение много к одному).

Общее решение вашей проблемы - получить только самую последнюю запись - использовать подзапрос на tb_updates (см. Псевдоним mx ниже), а затем присоединить это обратно к tb_updates, чтобы только запись, имеющая последнюю дату выбран.

SELECT 
     t.* 
    , u.* 
FROM tb_ticket t 
     INNER JOIN tb_updates u 
        ON t.ticket_id = u.ticket_id 
     INNER JOIN (
        SELECT 
         ticket_id 
         , MAX(updated_at) max_updated 
        FROM tb_updates 
        GROUP BY 
         ticket_id 
      ) mx 
        ON u.ticket_id = mx.ticket_id 
         AND u.updated_at = mx.max_updated 
; 

Если у вас есть СУБД, которая поддерживает ROW_NUMBER(), то с помощью этой функции может быть очень эффективным альтернативным методом, но вы не сообщили нам, какие DBMS вы используете.


кстати: Эти строки различны:

67355;69759;"COMPANY X";"2014-08-22 09:40:21";"OPEN";"John";1 
67355;69771;"COMPANY X";"2014-08-26 10:40:21";"UPDATE";"John";1 

69759 отличается от 69771, и это достаточно для 2 ряда, чтобы быть DISTINCT есть разница в 2 датами также ,

distinct is row operator, который означает, что вся строка, а не только первый столбец, определяет, какие строки уникальны.

+0

Даже с плохой информацией, которую я дал, вы могли бы решить мою проблему полностью. Это невероятно! Большое вам спасибо, он отлично работает! Это именно то, что я искал! –

+0

К сожалению, вы не понимаете, что SO здесь не просто для решения ваших проблем, а для создания четких проблем и решений, которые могут помочь другим, подобным вам (или мне) в будущем. Хороший вопрос не дает «плохой информации». – Frazz

0

U Может попробовать что-то, как показано ниже, если ваш UpdateID является столбцом идентификаторов:

Select ticketed, max(updateid) from table 
group by ticketed 
0

Чтобы получить последнюю строку, вы должны закончить свой запрос с order by time desc затем использовать TOP (1) в операторе выбора, чтобы выбрать только первую строку результат запроса

например:

select TOP (1) ..... 
     from ..... 
     where ..... 
     order by time desc 
1

Решение Used_By_Already будет работать нормально. Я не уверен в производительности, но другим решением будет использование cross apply, хотя это ограничивается только несколькими СУБД.

SELECT * 
FROM tb_ticket ticket 
CROSS APPLY (
    SELECT top(1) * 
    FROM tb_updates details 
    ORDER BY updateTime desc 
    WHERE details.ticketID = ticket.ticketID 
    ) updates 
+0

на самом деле он защитит вас от получения более 1 записи, если есть привязка к обновленному значению времени. Но, @Kiklion, я бы предположил row_number(), прежде чем применять крест, поскольку он более широко доступен. –

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