Нужен сложный SQL-запрос - PullRequest
1 голос
/ 17 февраля 2009

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

В основном мне нужен запрос, который будет возвращать одну строку для каждого case_id , где тип support , статус start , а дата означает самый первый один созданный (так что в приведенном ниже примере возвращается только случай Джона 2/2/2009, а не 3/1/2009). Поиск должен быть динамическим, чтобы можно было возвращать все похожие строки с разными case_id и т. Д. Из таблицы с тысячами строк.

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

ID   |  Case_ID   |   Name   |   Date   |  Status  |  Type   

48   |    450     |   John   | 6/1/2009 |  Fixed   | Support   
47   |    450     |   John   | 4/1/2009 |  Moved   | Support   
46   |    451     |   Sarah  | 3/1/2009 |          |           
45   |    432     |   John   | 3/1/2009 |  Fixed   | Critical  
44   |    450     |   John   | 3/1/2009 |  Start   | Support 
42   |    450     |   John   | 2/1/2009 |  Start   | Support   
41   |    440     |   Ben    | 2/1/2009 |          |           
40   |    432     |   John   | 1/1/2009 |  Start   | Critical  
...

Спасибо большое!

Edit:

Чтобы ответить на вопросы некоторых людей, я использую SQL Server 2005. И дата - это просто обычная дата, а не строка.

Хорошо, теперь я попал в проблему. Я закончил с решением Bliek, которое работало как шарм. Но теперь я столкнулся с проблемой, что иногда статус никогда не запускается, так как он решается немедленно. Я должен включить это также. Но только на определенный период времени.

Я предполагаю, что мне придется проверить таблицу дел, на которую ссылается FK Case_ID здесь. Поэтому мне нужен способ проверить каждый Case_ID, созданный в CaseTable за последний месяц, а затем выполнить поиск по той же таблице и таким же образом, как указано выше, возвращая только первый результат, как и раньше. Как я могу использовать другую таблицу таким образом?

Как обычно, я постараюсь найти ответ сам во время ожидания, еще раз спасибо!

Редактировать 2:

Кажется, это ответ. У меня пока нет доступа к полной БД, поэтому я не могу полностью протестировать ее, но, похоже, она работает с фиктивными таблицами, которые я создал, чтобы продолжить из предложения WHERE кода Блика:

WHERE RowNumber = 1 AND Case_ID IN (SELECT Case_ID FROM CaseTable
      WHERE (Date BETWEEN '2007/11/1' AND '2007/11/30'))

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

Ответы [ 4 ]

4 голосов
/ 17 февраля 2009

Может быть что-то вроде:

select Case_ID, Name, MIN(date), Status, Type 
from table
where type = 'Support'
 and status = 'Start'
group by Case_ID, Name, Status, Type 

РЕДАКТИРОВАТЬ: Вы не предоставили много подробностей о том, что вы действительно хотите, поэтому я предлагаю вам прочитать все ответы и выбрать тот, который лучше всего подходит для вашей проблемы. Пока что я бы сказал, что ответ Томалака ближе всего к тому, что вы ищете ...

3 голосов
/ 17 февраля 2009
SELECT
  c.ID,
  c.Case_ID,
  c.Name,
  c.Date,
  c.Status,
  c.Type
FROM
  CaseTable c
WHERE
  c.Type = 'Support'
  AND c.Status = 'Start'
  AND c.Date = (
    SELECT MIN(Date) 
    FROM CaseTable
    WHERE Case_ID = c.Case_ID AND Type = c.Type AND Status = c.Status)
/* GROUP BY only needed when for a given Case_ID several rows 
   exist that fulfill the WHERE clause */
GROUP BY
  c.ID,
  c.Case_ID,
  c.Name,
  c.Date,
  c.Status,
  c.Type

Этот запрос значительно выигрывает от индексов для столбцов Case_ID, Date, Status и Type.

Добавленная ценность, хотя тот факт, что фильтр на Support и Status нужно устанавливать только в одном месте.

В качестве альтернативы предложению GROUP BY вы можете сделать SELECT DISTINCT, что повысит читабельность (это может повлиять или не повлиять на общую производительность, я предлагаю вам сравнить оба варианта друг с другом). Если вы уверены, что в вашей таблице нет Case_ID двух строк с одинаковой датой, вам вообще не понадобится GROUP BY или SELECT DISTINCT.

1 голос
/ 17 февраля 2009

В SQL Server 2005 и более поздних версиях я использовал бы общие табличные выражения (CTE). Это предлагает множество возможностей, таких как:

With ResultTable (RowNumber
                 ,ID
                 ,Case_ID
                 ,Name
                 ,Date
                 ,Status
                 ,Type)
AS
(
    SELECT Row_Number() OVER (PARTITION BY Case_ID
                                  ORDER BY Date ASC)

          ,ID
          ,Case_ID
          ,Name
          ,Date
          ,Status
          ,Type
      FROM CaseTable
     WHERE Type   = 'Support'
       AND Status = 'Start'
)
    SELECT ID
          ,Case_ID
          ,Name
          ,Date
          ,Status
          ,Type
      FROM ResultTable
     WHERE RowNumber = 1
0 голосов
/ 17 февраля 2009

Не извиняюсь за форматирование даты, в этом есть смысл.

    SELECT ID, Case_ID, Name, MIN(Date), Status, Type
    FROM caseTable
    WHERE Type = 'Support'
       AND status = 'Start'
    GROUP BY ID, Case_ID, Name, Status, Type
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...