2015-11-26 2 views
0

Я относительно новичок в sql-запросах, и мне было интересно, как создать сложную хранимую процедуру. Моя база данных работает на SQL-сервере.if-then-else конструкция в сложной хранимой процедуре

У меня есть клиент таблицы (id, name) и таблица customer_events (id, customer_id, timestamp, action_type). Я хочу добавить вычисляемое поле customer_status для таблицы клиентов

  • 0: (если нет события для этого клиента в customer_events) или (самое последнее событие> 5 минут назад)
  • 1: если самое последнее событие < 5 минут назад и ACTION_TYPE = 0
  • 2: если последнее событие < 5 минут назад и ACTION_TYPE = 1

Могу ли я использовать если-то-иначе конструкции или я должен решить эту проблему по-другому?

+1

'IF..THEN' очень процедурный, тогда как (большую часть времени) sql основан на наборе. То, что вы на самом деле хотите, - это оператор CASE. Когда вы говорите, что хотите «вычисленное поле в таблице клиентов», действительно ли это * действительно вычисленное поле, которое вы хотите, или вы хотите добавить это поле в запрос выбора к таблице клиентов? – Jamiec

+0

oke, спасибо. Я хочу добавить это поле в запрос выбора из таблицы клиентов. Как я мог это достичь? – gmeuleman

+0

Если вы хотите добавить его в таблицу, вам нужно задание, которое выполняется периодически, если вам нужно, чтобы он был добавлен как часть, если набор результатов, вы просто вычисляете его в инструкции selct (используя левое соединение и оператор case). – jmoreno

ответ

0

Как упоминалось в комментариях, вы на самом деле хотите, чтобы добавить поле запроса на выборку, и в общем смысле, что вы хотите это CASE заявление. Они работают следующим образом:

SELECT field1, 
     field2, 
     CASE 
     WHEN some_condition THEN some_result 
     WHEN another_condition THEN another_result 
     END AS field_alias 
FROM table 

Применительно к вашему конкретному сценарию, ну это не совсем просто. Вам обязательно понадобится left join ваша таблица состояния, вы также хотите, чтобы агрегировать, чтобы найти самое последнее событие, а также тип действия этого события. После того, как у вас есть эта информация, заявление о делах прост.

Всегда трудно писать SQL без доступа к данным, но что-то вроде:

SELECT c.id, 
     c.name, 
     CASE 
      WHEN e.id IS NULL OR DATEDIFF(minute,e.timestamp,getDate())>=5 THEN 0 
      WHEN DATEDIFF(minute,e.timestamp,getDate())<5 AND s.action_type=1 THEN 1 
      WHEN DATEDIFF(minute,e.timestamp,getDate())<5 AND s.action_type=0 THEN 2 
     END as customer_status 
FROM clients c 
LEFT JOIN (
    SELECT id, client_id, action_type, 
      rank() OVER(partition by client_id order by timestamp desc) AS r 
    FROM customer_events 
) e 
ON c.id=e.client_id AND e.r=1 

Ядро это подзапрос в середине, он использует rank Funtion, чтобы дать номер каждому статус, client_id заказывается по убыванию времени. Поэтому каждая запись с рангом 1 будет самой последней (для этого клиента). После этого вы просто присоединяете его к таблице клиентов и используете его для определения правильного значения для customer_status

+0

Большое спасибо @jamiec. Это решило мою проблему! – gmeuleman

0

Предполагая, что вы получите информацию о мероприятии в «Most_Recent_Event_Mins_Ago». Если ни один, это будет NULL.

SELECT Id, Name, 
     CASE 
      WHEN Most_Recent_Event_Mins_Ago IS NULL THEN 0 
      WHEN Most_Recent_Event_Mins_Ago <5 AND Action_type = 0 THEN 1 
      WHEN Most_Recent_Event_Mins_Ago <5 AND Action_type = 1 THEN 0 
      ..other scenarions 
      ELSE yourDefaultValueForStatus 
     END as Status 
FROM customer 
WHERE 
... 
... 
Смежные вопросы