Get the reply of an outgoing message in the same row in SQL? - sql

I am trying to get the incoming message for an outgoing message in the same row as response? So, the data looks like below:
user_id message type
1 What's your name? outgoing
1 Nitin incoming
1 What's your age? outgoing
1 17 incoming
2 What's your name? outgoing
2 Aayush incoming
2 What's your age? outgoing
3 What's your name? outgoing
4 What's your name? outgoing
4 Shubham incoming
4 What's your age? outgoing
The output should look like:
user_id message type reply
1 What's your name? outgoing Nitin
1 Nitin incoming
1 What's your age? outgoing 17
1 17 incoming
2 What's your name? outgoing Aayush
2 Aayush incoming
2 What's your age? outgoing No-reply
3 What's your name? outgoing No-reply
4 What's your name? outgoing Shubham
4 Shubham incoming
4 What's your age? outgoing No-reply
The reply is an incoming message for an outgoing message for a user_id & if there is no reply for an outgoing message then the reply column should be filled by 'No-reply'. I have to do this in PSQL. I am currently able to do this in python after fetching data from DB.
Below is my current python code.
df['reply'] = np.where((df['user_id'] == df['user_id'].shift(-1))
& (df['type'].eq('Outgoing') & df['type'].shift(-1).eq('Incoming')),
df['message'].shift(-1), 'No-reply')

Assuming that you have a column that can be used to order the records (called id), you could use lead() as follows:
select
t.*,
case
when type = 'outgoing'
and lead(type) over(partition by user_id order by id) = 'incoming'
then lead(message) over(partition by user_id order by id)
when type = 'outgoing' then 'no reply'
end reply
from mytable
This query checks if the current record has type outgoing and if the next one (for the same user) is of type incoming: if both conditions are true, then it recovers the message on the next record and displays it as reply. If type is outgoing but the next message is not incoming, then it gives no reply. In other cases, nothing is printed.

Related

Query NPS Radius SQL log for reject events

I'd like to have a SQL query to find only radius reject events (type=3). The previous row is also required to know the user name that was rejected.
Data looks like this:
id
timestamp
NPS_Svr
Packet_Type
Description
User-Computer
27949
1:25:46 PM
SVR1
2
Access Accept
NULL
27948
1:25:46 PM
SVR1
1
Access Request
user1
27947
1:25:36 PM
SVR1
3
Access REJECT
NULL
27946
1:25:36 PM
SVR1
1
Access Request
user1
27945
1:25:33 PM
SVR3
2
Access Accept
NULL
27944
1:25:33 PM
SVR3
1
Access Request
user2
27943
1:25:21 PM
SVR3
3
Access REJECT
NULL
27942
1:25:21 PM
SVR3
1
Access Request
user2
select *
from accounting_data
where packet_type=3
Returns the reject rows but I also need the previous row from the same NPS Server to know the user name that was rejected.
The server is MS SQL 2014.
As I understand previous row it's
according to sort order of id columns,
So I suggest to self join by id-1
SELECT main.*,past.user_computer FROM (
select m.*,RANK() OVER (PARTITION BY nps_svr ORDER BY id ) as RnKSer
from accounting_data m
) main left join (SELECT nps_svr,RnKSer-1 as PastRnKSer,user_computer
FROM (
select m.*,RANK() OVER (PARTITION BY nps_svr ORDER BY id ) as RnKSer
from
accounting_data m
) prev ) past on main.nps_svr=past.nps_svr and RnKSer=PastRnKSer
where packet_type=3
ORDER BY 1

SQL How to flag a given sessionID based on values from another column

Forgive me I'm not massively familiar with SQL to do the below. But would love to learn the process of how to do it if possible.
I only have one table: Table name - SessionTracker
-----------------------------------------------------------------------------------------------------------------------------------
bundleID | sessionId | deviceID | eventType | codeValue
------------------------------------------------------------------------------------------------------------------------------------
com.package.random 3871207406642403679 333333-00000-0000-00000-000000000000000 REQUEST 1
com.package.random 3871207406642403679 333333-00000-0000-00000-000000000000000 EVENT 1
com.package.random 3871207406642403679 333333-00000-0000-00000-000000000000000 RESPONSE 1
com.package.random 3245233406642403679 000000-00000-0000-00000-000000000000000 REQUEST 1
com.package.random 3245233406642403679 000000-00000-0000-00000-000000000000000 EVENT 2
com.package.random 3245233406642403679 000000-00000-0000-00000-000000000000000 RESPONSE 2
com.package.random 871207406643e243433 000000-00000-0000-00000-000000000000000 REQUEST 1
com.package.random2 3243254325454535422 111111-00000-0000-00000-000000000000000 REQUEST 1
com.package.random3 4353453452525252465 222222-00000-0000-00000-000000000000000 REQUEST 1
com.package.random4 3453656456353252345 111111-00000-0000-00000-000000000000000 REQUEST 1
com.package.random5 4567568765745634563 111111-00000-0000-00000-000000000000000 REQUEST 1
I'd like to
Select all the sessions where the codeValue was different within that session.
From the example above:
I want to check is if a session which consists of request, event & response has a different value in one of each. Like the sessionId above (3871207406642403679) the code value is 1 in each so this wouldn't be flagged.
The second sessionId (3245233406642403679) the code value in one of the request, event & response has the code value 2 for event and response, so this would be flagged.
I'm hoping a query in databricks would work, is this possible?
In SQL, you could do this with aggregation and a having clause:
select sessionId
from mytable
group by sessionId
having min(codeValue) <> max(codeValue)
This gives you all sessionIds that have at least two distinct codeValues.

Select X.A and X.B from X, then count all rows from Y where Y.A = X.A and Y.B > X.B

I have three tables: conversations, participants, and messages:
+---------------+
| conversations |
+---------------+
| id |
+---------------+
+-----------------------------------------------------+
| participants |
+-----------------+----------------+------------------+
| conversation_id | participant_id | last_read | // "participant_id" is the id of the user.
+-----------------+----------------+------------------+
+---------------------------------------------------------------+
| messages |
+----+-----------------+-----------+------------------+---------+
| id | conversation_id | sender_id | sending_time | content |
+----+-----------------+-----------+------------------+---------+
Sample data on SQL Fiddle
My ultimate goal is to count the total number of messages the user did not read. If the message sending_time is grater then the conversation last_read value, then the user did not read the message.
Example (using the sample data): Let's say I want to count the number of unread messages of user 2. As we can see in the sample data, in conversation 1 he received 2 messages from user 1 (messages 1 and 3), and in conversation 2 he recieved 1 message from user 1 (message 4). Since user 2 last read conversation 1 at 10:30, there is 1 unread message in conversation 1 (message 3), and since he did not yet read conversation 2, there is 1 unread message in conversation 2, so we have a total of 2 unread messages in all conversations, and that should be the result.
My first try was to approach this part-SQL part-Code. So first I executed the following query from my C# program, which fetches all the conversations the user participates in:
SELECT conversation_id, last_read
FROM participants
WHERE participant_id = {user_id}
Then, for each result of the previous query, I executed the following query:
SELECT COUNT(*)
FROM messages
WHERE
conversation_id = {result.conversation_id}
AND
sender_id <> {user_id}
AND
sending_time > {result.last_read}
And finally, I programmatically summed up the results of all the COUNTs. All of this works just fine.
However, for many reasons, I need to refactor this code to be 100% SQL, and I am not sure how to accomplish this. I believe that the process should be along the lines of the "query" in the title. How can I do that?
Thanks.
I think this is just a join with appropriate filters:
select count(*)
from messages m join
participants p
on p.conversation_id = m.conversation_id
where p.participant_id = {user_id} and
p.last_read < m.sending_time;
if you want to convert into sql query try this.
select count * from conversations c join participants p on conversations.id = participants.conversation_id join messages m on messages.conversation_id = participants.conversation_id where m.sender_id > p.last_read

SQL results to get email thread

I have a message system table. It stores the typical from, to, and even about (3-way system) and the RepliedToID...the ID of the message that this one may be a reply to. Each message can have several replies. It can eventually create a thread of messages chained together.
I'm stumped as to how I can create a query that can take any message in the thread with the ID and retrieve messages before and after on the thread.
=============
MID ReplyID Message
1 First Message
2 1 Second Mess replied to #1
3 2 Third Mess replied to #2
4 2 Fourth Mess replied to #2
5 4 Fifth Mess replied to #4
=============
If I had any single MID in this, is there a way to get the results for all messages in the thread? (of Course, there will be all kinds of messages mixed in between these as the MID is an autonumber key)
Using the following table and data :
MID ReplyId Message
1 0 First Message f
2 1 Second Mess replied to #1
3 2 Third Mess replied to #2
4 2 Fourth Mess replied to #2
5 4 Fifth Mess replied to #4
6 0 New thread
7 6 Reply to new thread
8 4 Reply to #4
If you use a SQL Statement similar to this :
SELECT t1.MID, t1.Message, t2.ReplyID, t2.Message as Msg_Reply
FROM test_table t1
CROSS JOIN test_table t2 ON t1.MID = t2.ReplyID
ORDER BY ReplyID
It gives you back a table like this
MID Message ReplyID Msg_Reply
1 First Message 1 Second Mess replied to #1
2 Second Mess replied to #1 2 Third Mess replied to #2
2 Second Mess replied to #1 2 Fourth Mess replied to #2
4 Fourth Mess replied to #2 4 Fifth Mess replied to #4
4 Fourth Mess replied to #2 4 Reply to 4
6 New thread 6 Reply to new thread
I guess after that you could just loop through these data and display it following the thread.

Counting Distinct Values with multiple criteria

I have an Excel file with the below data example:
IssueNumber Client
100 Client 1
100 Client 1
101 Client 1
102 Client 2
102 Client 2
I want to count the number of unique IssueNumbers for each client. So the end result would be:
Client Count
Client 1 2
Client 2 1
I have a list of the clients in a separate tab from the main data, and am trying to look up using COUNTIFS, and passing the Client name as one of the criteria, but I am struggling to figure out how to count the unique issues.
This must be really simple, but it is Friday afternoon and my brain has given up!
Its Friday Morning here so I am not so burnt out yet,
=SUMPRODUCT(($B$2:$B$6=D2)*1/COUNTIF($A$2:$A$6,$A$2:$A$6))
Few more options:
=SUM(IF(((MATCH($A$2:$A$6&$B$2:$B$6,$A$2:$A$6&$B$2:$B$6,0))>=(ROW($A$2:$A$6)-(MIN(ROW($A$2:$A$6))-1)))*($B$2:$B$6=D2)=1,1,0))
&
=SUM(IF(FREQUENCY(IF($B$2:$B$6=D2,MATCH($A$2:$A$6&"_"&$B$2:$B$6,$A$2:$A$6&"_"&$B$2:$B$6,0)),ROW($A$2:$A$6)-ROW($A$2)+1),1))
Both the above formulas are array formula so should be entered by pressing Ctrl+Shift+Enter.