Фильтрация запросов SQL - PullRequest
0 голосов
/ 18 февраля 2009

Используя SQL Server 2005, у меня есть таблица, в которой регистрируются определенные события, и мне нужно создать запрос, который возвращает только очень конкретные результаты. Ниже приведен пример:

<b>Log:</b>
Log_ID | FB_ID |   Date    | Log_Name | Log_Type

   7   |   4   | 2007/11/8 |   Nina   |  Critical
   6   |   4   | 2007/11/6 |   John   |  Critical
   5   |   4   | 2007/11/6 |   Mike   |  Critical
   4   |   4   | 2007/11/6 |   Mike   |  Critical
   3   |   3   | 2007/11/3 |   Ben    |  Critical
   2   |   3   | 2007/11/1 |   Ben    |  Critical

Запрос должен выполнять следующее: возвращать ТОЛЬКО по одной строке для каждого FB_ID, но это должна быть та строка, в которой Log_Name изменено впервые, или, если имя никогда не изменяется, то первая строка с датой.

С точки зрения непрофессионала, мне нужно это, чтобы просмотреть БД, чтобы проверить для каждого случая, когда ответственность за дело (FB_ID) была передана другому человеку, а в случае, если это никогда не происходит, просто получите имя исходного регистратора.

В приведенном выше примере я должен получить строки (Log_ID) 2 и 6.

Это вообще возможно? Сейчас идет дискуссия о том, была ли БД сделана неправильно. :)

Я предполагаю, что мне нужно каким-то образом сохранить первое полученное имя Log_Name в переменной, а затем сравнить его с условием IF и т. Д. Однако я не знаю, как сделать это с SQL.

Редактировать: Обновлена ​​дата. И чтобы уточнить это, правильный результат будет выглядеть так:

Log_ID | FB_ID |   Date    | Log_Name | Log_Type

   6   |   4   | 2007/11/6 |   John   |  Critical
   2   |   3   | 2007/11/1 |   Ben    |  Critical

Это не первая дата для FB_ID, за которой я следую, но строка, в которой Log_Name изменяется от оригинала.

Первоначально FB_ID 4 принадлежал Майку, но запрос должен возвращать строку, в которой он переходит к Джону. Тем не менее, он НЕ должен возвращать строку, где он движется дальше, к Нине, потому что первое изменение ответственности уже произошло, когда Джон получил его.

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

Ответы [ 3 ]

3 голосов
/ 18 февраля 2009

Я думаю, что есть лучший и более эффективный способ, но этот, кажется, работает:

SELECT *
  FROM log
 WHERE log_id IN
   ( SELECT MIN(log_id)
       FROM log
      WHERE
         ( SELECT COUNT(DISTINCT log_name)
                FROM log log2
               WHERE log2.fb_id = log.fb_id ) = 1
         OR log.log_name <> ( SELECT log_name
                                FROM log log_3
                               WHERE log_3.log_id =
                                 ( SELECT MIN(log_id)
                                     FROM log log4
                                    WHERE log4.fb_id = log.fb_id ) )
      GROUP BY fb_id )
2 голосов
/ 18 февраля 2009

Это будет эффективно использовать индекс для (fb_id, cdate, id):

SELECT  lo4.*
FROM
    (
    SELECT  CASE WHEN ln.log_id IS NULL THEN lo2.log_id ELSE ln.log_id END AS log_id,
            ROW_NUMBER() OVER (PARTITION BY lo2.fb_id ORDER BY lo2.cdate) AS rn
    FROM    (
        SELECT
            lo.*,
            (
            SELECT  TOP 1 log_id
            FROM    t_log li
            WHERE   li.fb_id = lo.fb_id
                    AND li.cdate >= lo.cdate
                    AND li.log_id <> lo.log_id
                    AND li.log_name <> lo.log_name
            ORDER BY
                cdate, log_id
            ) AS next_id
        FROM t_log lo
        ) lo2
    LEFT OUTER JOIN
        t_log ln
    ON ln.log_id = lo2.next_id
    ) lo3, t_log lo4
WHERE lo3.rn = 1
    AND lo4.log_id = lo3.log_id
0 голосов
/ 18 февраля 2009

Если я правильно понял проблему, то следующий SQL должен помочь:

SELECT Log_ID, FB_ID, min(Date), Log_Name, Log_Type  
FROM Log  
GROUP BY Date

SQL выберет строку с самой ранней датой для каждого FP_ID.

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