SQL Server How to use LEAD() function with null value on T-SQL

b4lqfgs4  于 2023-03-28  发布在  其他
关注(0)|答案(1)|浏览(78)

Context - some agents send or not different types of messages, the date messages are recorded.

Sometimes several agents are presents on the same event (mess_id on the table below).

How to create columns by messages and retrieve for each message the minimum date if the agent send the same message and case if the message is not send.

Here is the table :
| mess_id | alltripid | categ_agent | message_order | type_message | dt_message |
| ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |
| 2022-12-19-2310-8891702 | 17 | x | 1 | enter | 2022-12-19 10:53:43 |
| 2022-12-19-2310-8891702 | 17 | x | 2 | mess1_to_give | NULL |
| 2022-12-19-2310-8891702 | 17 | x | 3 | mess1_given | NULL |
| 2022-12-19-2310-8891702 | 17 | x | 4 | mess2_to_give | NULL |
| 2022-12-19-2310-8891702 | 17 | x | 5 | mess2_given | NULL |
| 2022-12-19-2310-8891702 | 17 | x | 6 | mess_played | NULL |
| 2022-12-19-2310-8891702 | 17 | x | 7 | leave | NULL |
| 2022-12-19-2310-8891702 | 18 | y | 1 | enter | 2022-12-19 10:48:51 |
| 2022-12-19-2310-8891702 | 18 | y | 2 | mess1_to_give | 2022-12-19 10:57:13 |
| 2022-12-19-2310-8891702 | 18 | y | 3 | mess1_given | NULL |
| 2022-12-19-2310-8891702 | 18 | y | 4 | mess2_to_give | 2022-12-19 10:57:49 |
| 2022-12-19-2310-8891702 | 18 | y | 5 | mess2_given | 2022-12-19 10:57:58 |
| 2022-12-19-2310-8891702 | 18 | y | 6 | mess_played | NULL |
| 2022-12-19-2310-8891702 | 18 | y | 7 | leave | 2022-12-19 11:00:36.07 |

and the expected result :

mess_idalltripidcateg_agentmessage_ordertype_messagedt_messageentermess1_to_givemess1_givenmess2_to_givemess2_givenmess_playedleave
2022-12-19-2310-889170217x1enter19/12/2022 10:5319/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170217x2mess1_to_giveNULL19/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170217x3mess1_givenNULL19/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170217x4mess2_to_giveNULL19/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170217x5mess2_givenNULL19/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170217x6mess_playedNULL19/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170217x7leaveNULL19/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170218y1enter19/12/2022 10:4819/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170218y2mess1_to_give19/12/2022 10:5719/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170218y3mess1_given19/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170218y4mess2_to_give19/12/2022 10:5719/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170218y5mess2_given19/12/2022 10:5719/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170218y6mess_playedNULL19/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00
2022-12-19-2310-889170218y7leave19/12/2022 11:0019/12/2022 10:4819/12/2022 10:57NULL19/12/2022 10:5719/12/2022 10:57NULL19/12/2022 11:00

I am unable to use lead() and min() correctly in this case I don't know what the right solution is and I tried this for the first value and the last.

WITH first_step AS
(
    SELECT 
        *,
        CONCAT(mess_id, '-', type_message) AS mess_type_id,
        ROW_NUMBER() OVER (PARTITION BY type_message ORDER BY mess_id) AS rn_message
    FROM 
        mytable
),
second_step AS
(
    SELECT 
        *,
        MIN(dt_message) OVER (PARTITION BY mess_type_id ORDER BY mess_type_id) AS min_dt_mess
    FROM 
        first_step
)
SELECT 
    *,
    FIRST_VALUE(min_dt_mess) OVER (PARTITION BY mess_id ORDER BY message_order) AS enter,
    MIN(min_dt_mess) OVER (PARTITION BY mess_id ORDER BY message_order ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) mess_played,
    FIRST_VALUE(min_dt_mess) OVER (PARTITION BY mess_id ORDER BY message_order desc) AS leave
FROM 
    second_step
ORDER BY 
    categ_agent, message_order

See the Fiddle

zfycwa2u

zfycwa2u1#

One of the ways to get the desired result

SELECT mess_id, alltripid, categ_agent, message_order, type_message, dt_message,
  min(case when type_message ='enter' then dt_message end) OVER (PARTITION BY mess_id ORDER BY mess_id) as enter,
  min(case when type_message ='mess1_to_give' then dt_message end) OVER (PARTITION BY mess_id ORDER BY mess_id) as mess1_to_give,
  min(case when type_message ='mess1_given' then dt_message end) OVER (PARTITION BY mess_id ORDER BY mess_id) as mess1_given,
  min(case when type_message ='mess2_to_give' then dt_message end) OVER (PARTITION BY mess_id ORDER BY mess_id) as mess2_to_give,
  min(case when type_message ='mess2_given' then dt_message end) OVER (PARTITION BY mess_id ORDER BY mess_id) as mess2_given,  
  min(case when type_message ='mess_played' then dt_message end) OVER (PARTITION BY mess_id ORDER BY mess_id) as mess_played,
  min(case when type_message ='leave' then dt_message end) OVER (PARTITION BY mess_id ORDER BY mess_id) as leave
  FROM mytable

See the Fiddle(https://dbfiddle.uk/iwx0MzHZ)

相关问题