Search string value from mssql column, regex, group by - sql

These data:
ID Desc
1 CUSTSEG
2 CUSTSEG;CARDMNU;CRC;CRCBISOA;CARDMNU;CRC;CRCBISOA
3 CUSTSEG;HKM
4 CUSTSEG;HKM;HKM
5 CUSTSEG;HKM;HKM;HKM;HKM;HKM;HKM;HKM
6 CUSTSEG;PHPM
7 CUSTSEG;PHPM;CARDMNU
8 CUSTSEG;PHPM;CARDMNU;ATM
must be queried into this format:
COUNT Desc
1 ATM
4 CARDMNU
2 CRC
2 CRCBISOA
8 CUSTSEG
10 HKM
3 PHPM
How can I achieve this using? Substring? I've tried this:
SELECT COUNT(*), CallTraversalLog
FROM [IVR].[dbo].[tblReportData]
WHERE CallTraversalLog Like '%CUSTSEG%'
GROUP BY CallTraversalLog
But the resultset I got is
COUNT Desc
1 CUSTSEG;PHPM;CARDMNU;CRC;ATM
1 CUSTSEG;PHPM;CARDMNU;CRC;CARDMNU;CRC
1 CUSTSEG;PHPM;CARDMNU;CRC;CARDMNU;CRC;CRCBISOA
2 CUSTSEG;PHPM;CARDMNU;CRC;CC
3 CUSTSEG;PHPM;CARDMNU;CRC;CRC
2 CUSTSEG;PHPM;CARDMNU;CRC;CRC;CARDMNU;CRC
1 CUSTSEG;PHPM;CARDMNU;CRC;CRC;CRC;CRC;CARDMNU;CRC
25 CUSTSEG;PHPM;CARDMNU;CRC;CRCACTIVATION
4 CUSTSEG;PHPM;CARDMNU;CRC;CRCACTIVATION;CRCENROLL
55 CUSTSEG;PHPM;CARDMNU;CRC;CRCAPST

I would split the strings and count the items. You need a table valued function that splits a string by delimiter. If you don't want to write your own function you can easily google one. Then CROSS APPLY the function to your table and count the items.
SELECT s.item, count(*)
FROM [IVR].[dbo].[tblReportData] d
CROSS APPLY dbo.fnSplitString(d.CallTraversalLog, ';') s
GROUP BY s.item

Related

SQL order groups of data

Here I have a data sample:
Title
Size
Count
First
3
14
First
5
3
Second
2
5
First
2
10
Third
3
10
Second
3
4
Third
2
9
Third
5
11
Second
5
4
Now I want to sort the data with following rules:
Put the records with same title together: First followed by First, Second followed by Second.
Then for each group, order them by size;
For groups, order them in the sum of count of each group, like: sum of First is 14+3+10=27, Second is 5+4+4=13, Third is 10+9+11=30.
The result I want:
Title
Size
Count
Second
2
5
Second
3
4
Second
5
4
First
2
10
First
3
14
First
5
3
Third
2
9
Third
3
10
Third
5
11
It's an easy sort once you get the total "Count" per Title.
A SUM OVER can be used for that.
SELECT
q.title AS "Title"
, q.size AS "Size"
, q.count AS "Count"
FROM
(
SELECT t.title, t.size, t.count
, SUM(t.count) OVER (PARTITION BY t.title) AS TotalCount
FROM yourtable t
) q
ORDER BY q.TotalCount, q.title, q.size
Title
Size
Count
Second
2
5
Second
3
4
Second
5
4
First
2
10
First
3
14
First
5
3
Third
2
9
Third
3
10
Third
5
11
Demo on db<>fiddle here
You can join the results of the group count sums back onto the main table, using the sums in the order by clause:
select t.* from tbl t join
(select t1.title, sum(t1.cnt) s from tbl t1 group by t1.title) t2
on t.title = t2.title order by t2.s, t.title, t.size;
Another approach is by using WITH Queries (Common Table Expressions)
with ct
as (
select title
,size
,count
,sum(count) over (partition by title) sm
from tbl
)
select title
,size
,count
from ct
order by ct.sm,2;

Row Number with specific window size

I want to group records by row numbers.
Like from row 1-3 in group 1 , 4-6 in group 2 , 7-9 in group 3 and so on.
Suppose below is the table structure:
Row NumberDataValue
1 A 10
2 A 5
3 A 1
4 A 33
5 A 2
6 A 127
1 B 1
2 B 0
3 B 7
4 B 7
5 B 5
6 B 8
7 B 1
8 B 0
I want a output like this:
GroupValue
1 10
1 5
1 1
2 33
2 2
2 127
1 1
1 0
1 7
2 7
2 5
2 8
3 1
3 0
I am using Oracle 11G.
I can achieve this using PL/SQL. But I have to use SQL only. As I have to use this query in a reporting tool.
If this is a duplicate question please provide the link of the answered question.
Subtract 1 from the column "RowNumber" and divide by 3.
Then use TRUNC() to get the integer part:
SELECT TRUNC(("RowNumber" - 1) / 3) + 1 "Group",
"Value"
FROM tablename
See the demo.
I would assume the name of the first column is ordering.
You can do:
select
1 + trunc(row_number() over(partition by data order by ordering) - 1) / 3,
value
from t
What you show looks like the output from something like this:
select ceil(rn/3) as grp, value
from your_table
order by rn;
Note that "row number" and "group" are reserved words/phrases which should not be used as column names. I used rn and grp instead.
I think the ceiling function is the simplest way to arrive at what you want. If you want to base it on the RowNumber column:
select ceil( RowNumber / 3.0) as grouping
If you want to calculate it yourself using row_number():
select ceil( row_number() over (order by RowNumber) / 3.0 ) as grouping

Postgres The plpgsql aggregate function filters the length of each group

For plpgsql aggregate function help, not sure whether it can be realized. Thanks in advance for your help
Table
_id group_id content num len
0 2 tab 1 3
1 2 name 2 4
2 1 tag 1 3
3 1 bag 2 3
4 1 a 3 1
5 2 b 3 1
6 1 bo 4 2
7 2 an 4 2
I want to implement an aggregation function to aggregate according to group_id, and num is processed in sorted order, and then judge in the function to skip if len is less than or equal to 2, and then return the data of the specified length after each aggregation.
example:
with sorted_table as(select * from Table order by num)
select my_func(content, len, 2(required_num)) from sorted_table group by group_id;
expect result
_id group_id content num len
0 2 tab 1 3
1 2 name 2 4
2 1 tag 1 3
3 1 bag 2 3
for example, need to sort the top 10 (required_num) in each group, sort according to the num of each group, and compare the contents of the top 10 in turn. If the similarity is too high(i can use select similarity judge), filter out, and so on to reach 10 per group Claim. It may also be this
group_id result
2 [{"num":1,"content":"tab","len":3,"_id":0},{"num":2,"content":"name","len":4,"_id":1}]
1 [{"num":1,"content":"tag","len":3,"_id":2},{"num":2,"content":"bag","len":3,"_id":3}]
As far as I understand the question, you don't really need the custom aggregate:
select group_id,
jsonb_agg(t) filter (where len <= 2) as result
from the_table t
group by group_id;

How do I convert SQL data from one view to this other view in Postgres

I have table with data like this
id group order value
-------------------------
1 1 1 23
2 1 2 34
3 2 1 234
4 2 2 77
5 2 3 102
I want to insert into table so I have one row per group, with the value showing a string of comma-separated values orders based on the order.
id group value
----------------
1 1 23,34
2 2 234,77,102
How do I do this? I'm using Postgres 9.3
Postgres supports string_agg():
select row_number() over () as id, "group", string_agg(value, ',' order by "order")
from t
group by "group";
I would look at PostgreSQL's string_agg aggregate function.

Sum rows with the same ID

The following is an example of what I have to work with.
Sample data :
ID RANK
---------
1 2
1 3
2 4
2 1
3 2
2 3
4 2
SQLFiddle
I am trying to combine the rows with like IDs and sum the RANKs for these IDs into a single row:
ID SUM(rank)
1 5
2 8
3 2
4 2
You can use sum aggregate function together with the group by clause:
select [ID]
, sum([RANK])
from [STUFF]
group by [ID]
SQLFiddle