Here's a way to do this without reading the whole file into memory at once in awk while being able to handle input coming from a pipe or a file (so it'd work even if the input was the output of some other command without creating a temp file to contain all of the input) and retaining the original input order and header.
Input from a file:
$ awk 'BEGIN{FS=OFS=","} {print (NR>1), $NF, ++cnt[$NF], NR, $0}' file |
sort -t, -k1,1n -k2,2 -k3,3nr |
awk -F, '$2!=p2{p2=$2; p3=$3} (NR==1) || (p3>1)' |
sort -t, -k4,4n |
cut -d, -f5-
entity,entity_type,component_id
lalal@hotmail.com,email,2222
15158112233,phone,3333
15158990000,phone,2222
hello,world@gmail.com,email,3333
fds_213445,device,3333
or input from a pipe:
$ cat file |
awk 'BEGIN{FS=OFS=","} {print (NR>1), $NF, ++cnt[$NF], NR, $0}' |
sort -t, -k1,1n -k2,2 -k3,3nr |
awk -F, '$2!=p2{p2=$2; p3=$3} (NR==1) || (p3>1)' |
sort -t, -k4,4n |
cut -d, -f5-
entity,entity_type,component_id
lalal@hotmail.com,email,2222
15158112233,phone,3333
15158990000,phone,2222
hello,world@gmail.com,email,3333
fds_213445,device,3333
Note that this approach allows you to take input from a pipe, not just from a file, so you can pipe the output of another command to it if you like. In the above only sort has to handle the whole input at once and it's designed to do so by using demand paging, etc. so it's extremely unlikely to have any issues handling large input.
Here's what the script is doing in steps so you can see how it works:
$ awk 'BEGIN{FS=OFS=","} {print (NR>1), $NF, ++cnt[$NF], NR, $0}' file
0,component_id,1,1,entity,entity_type,component_id
1,1111,1,2,bla@gmail.com,email,1111
1,2222,1,3,lalal@hotmail.com,email,2222
1,3333,1,4,15158112233,phone,3333
1,2222,2,5,15158990000,phone,2222
1,3333,2,6,hello,world@gmail.com,email,3333
1,4444,1,7,1327168,phone,4444
1,3333,3,8,fds_213445,device,3333
$ ... | sort -t, -k1,1n -k2,2 -k3,3nr
0,component_id,1,1,entity,entity_type,component_id
1,1111,1,2,bla@gmail.com,email,1111
1,2222,2,5,15158990000,phone,2222
1,2222,1,3,lalal@hotmail.com,email,2222
1,3333,3,8,fds_213445,device,3333
1,3333,2,6,hello,world@gmail.com,email,3333
1,3333,1,4,15158112233,phone,3333
1,4444,1,7,1327168,phone,4444
$ ... | awk -F, '$2!=p2{p2=$2; p3=$3} (NR==1) || (p3>1)'
0,component_id,1,1,entity,entity_type,component_id
1,2222,2,5,15158990000,phone,2222
1,2222,1,3,lalal@hotmail.com,email,2222
1,3333,3,8,fds_213445,device,3333
1,3333,2,6,hello,world@gmail.com,email,3333
1,3333,1,4,15158112233,phone,3333
$ ... | sort -t, -k4,4n
0,component_id,1,1,entity,entity_type,component_id
1,2222,1,3,lalal@hotmail.com,email,2222
1,3333,1,4,15158112233,phone,3333
1,2222,2,5,15158990000,phone,2222
1,3333,2,6,hello,world@gmail.com,email,3333
1,3333,3,8,fds_213445,device,3333
$ ... | cut -d, -f5-
entity,entity_type,component_id
lalal@hotmail.com,email,2222
15158112233,phone,3333
15158990000,phone,2222
hello,world@gmail.com,email,3333
fds_213445,device,3333