SQL Server "Group By" for an interesting case - tsql

I have a table like that
ID ORDER TEAM TIME
IL-1 1 A_Team 11
IL-1 2 A_Team 3
IL-1 3 B_Team 2
IL-1 4 A_Team 1
IL-1 5 A_Team 1
IL-2 1 A_Team 5
IL-2 2 C_Team 3
What I want is grouping the same named teams which are also sequential teams (Which is according to the ORDER column)
So the result table should look like
IL-1 1 A_Team 14
IL-1 2 B_Team 2
IL-1 3 A_Team 2
IL-2 1 A_Team 5
IL-2 2 C_Team 3
Thanks
Edit: Depending on the nang's answer, I added the ID column to my table.

There is a problem in your example. Why should rows #6 and #2 not be "sequential teams"?
1 A_Team 5
2 A_Team 3
However, maybe the following is usefull for you:
select neworder, name, sum([time]) from (
select min(n1.[order]) neworder, n2.[order], n2.name, n2.[time]
from mytable n1, mytable n2
where n1.Name = n2.Name
and n2.[order] >= n1.[order]
and not exists(select 1 from mytable n3 where n3.name != n1.name and n3.[order] > n1.[order] and n3.[order] < n2.[order])
group by n2.[order], n2.name, n2.[time]) x
group by neworder, name
Result:
neworder name (No column name)
1 A_Team 19
4 A_Team 2
3 B_Team 2
2 C_Team 3

Related

create new sql column to get new value

I have this transaction table how can I query to find if a person is a New Client,Returning-Member, Returning-Non-member. for instance id 1 is a new client when sequence = 1, They can only be a member/returning-member after a type(member) has been purchased for example id 1 and sequence 4 is a returning-Non-member because this is the first time they are buying a member. After that transaction seq 5 they are now a returning-member
while for id 2 never bought a member so first sequence will be new client but others will be returning-non-member until they buy a member.
Question
id
Type
Date
Sequence
1
Member
2021-02-24
4
1
product
2021-01-03
2
2
service
2022-04-21
5
1
product
2021-02-01
3
2
service
2022-02-16
3
1
Member
2022-02-03
6
1
Service
2021-10-23
5
2
product
2022-01-03
2
1
service
2020-12-16
1
2
product
2022-03-30
4
2
service
2021-12-01
1
1
Member
2022-04-03
7
Result
id
Type
Date
Sequence
New column
1
Member
2021-02-24
4
Returning-Non-member
1
product
2021-01-03
2
Returning-Non-member
2
service
2022-04-21
5
Returning-Non-member
1
product
2021-02-01
3
Returning-Non-Member
2
service
2022-02-16
3
Returning-Non-member
1
Member
2022-02-03
6
Returning-Member
1
Service
2021-10-23
5
Returning-Member
2
product
2022-01-03
2
Returning-Non-Member
1
service
2020-12-16
1
New Client
2
product
2022-03-30
4
Returning-Non-Member
2
service
2021-12-01
1
New Client
1
Member
2022-04-03
7
Returning-Member
You can do it in a pretty strait forward way with an additional subquery, but it's not the best way in terms of performance.
SELECT
*,
CASE
WHEN t.Sequence = 1 THEN 'New Client'
WHEN
EXISTS (
SELECT *
FROM YourTable AS th
WHERE
th.Date < t.Date
AND th.Id = t.Id
AND th.Type ILIKE 'Member'
) THEN 'Returning-Member'
ELSE 'Returning-Non-Member'
END AS Membership
FROM YourTable AS t

Map the column value against same sequences in PostgreSQL

I want to write a query as per below input and output
Input :-
Num Sr_no Exp_no
NULL 1 1
NULL 2 1
ABC_1 3 1
NULL 4 1
NULL 1 2
NULL 2 2
ABC_2 3 2
NULL 4 4
Expected Output:-
Num Sr_no Exp_no
ABC_1 1 1
ABC_1 2 1
ABC_1 3 1
ABC_1 4 1
ABC_2 1 2
ABC_2 2 2
ABC_2 3 2
ABC_2 4 4
As there is no details in question, this answer is on below assumptions
you want to fill num field based on exp_no grouping.
Assuming there is only one value in a exp_no group.
Try this:
with cte as
(
select distinct on (num,exp_no) num, exp_no
from test
where num is not null
order by 1)
select
coalesce(t1.num, cte.num),
t1.sr_no,
t1.exp_no
from test t1 left join cte on t1.exp_no=cte.exp_no
DEMO

KDB+: How to retrieve the rows immediately before and after a given row that conform to a specific logic?

Given the following table
time kind counter key1 value
----------------------------------------
1 1 1 1 1
2 0 1 1 2
3 0 1 2 3
5 0 1 1 4
5 1 2 2 5
6 0 2 3 6
7 0 2 2 7
8 1 3 3 8
9 1 4 3 9
How would one select the value in the first row
immediately after and immediately before each
row of kind 1 ordered by time where the key1
value is the same in both instances .i.e:
time value prevvalue nextvalue
---------------------------------------------
1 1 0n 2
5 5 3 7
8 8 6 0n
9 9 6 0n
Here are some of the things I have tried, though
to be honest I have no idea how to canonically achieve
something like this in q whereby the prior value has a
variable offset to the current row?
select
prev[value],
next[value],
by key1 where kind<>1
update 0N^prevval,0N^nextval from update prevval:prev value1,nextval:next value1 by key1 from table
Some advice or a pointer on how to achieve this would be great!
Thanks
I was able to use the following code to return a table meeting your requirements. If this is correct, the sample table you have provided is incorrect, otherwise I have misunderstood the question.
q)table:([] time:1 2 3 5 5 6 7 8 9;kind:1 0 0 0 1 0 0 1 1;counter:1 1 1 1 2 2 2 3 4;key1:1 1 2 1 2 3 2 3 3;value1:1 2 3 4 5 6 7 8 9)
q)tab2:update 0N^prevval,0N^nextval from update prevval:prev value1,nextval:next value1 by key1 from table
q)tab3:select from tab2 where kind=1
time value1 prevval nextval
---------------------------
1 1 2
5 5 3 7
8 8 6 9
9 9 8
The update statement in tab2:
update 0N^prevval,0N^nextval from update prevval:prev value1,nextval:next value1 by key1 from table
is simply adding 2 columns onto the original table with the previous and next values for each row. 0^ is filling the empty fields with nulls.
The select statement in tab3:
tab3:select from tab2 where kind=1
is filtering tab2 for rows where kind=1.
The final select statement:
select time,value1,prevval,nextval from tab3
is selecting the rows you want to be returned in the final result.
Hope this answers your question.
Thanks,
Caitlin

Recursive Cumulative Sum up to a certain value Postgres

I have my data that looks like this:
user_id touchpoint_number days_difference
1 1 5
1 2 20
1 3 25
1 4 10
2 1 2
2 2 30
2 3 4
I would like to create one more column that would create a cumulative sum of the days_difference, partitioned by user_id, but would reset whenever the value reaches 30 and starts counting from 0. I have been trying to do it, but I couldn't figure it out how to do it in PostgreSQL, because it has to be recursive.
The outcome I would like to have would be something like:
user_id touchpoint_number days_difference cum_sum_upto30
1 1 5 5
1 2 20 25
1 3 25 0 --- new count all over again
1 4 10 10
2 1 2 2
2 2 30 0 --- new count all over again
2 3 4 4
Do you have any cool ideas how this could be done?
This should do what you want:
with cte as (
select t.a, t.b, t.c, t.c as sumc
from t
where b = 1
union all
select t.a, t.b, t.c,
(case when t.c + cte.sumc > 30 then 0 else t.c + cte.sumc end)
from t join
cte
on t.b = cte.b + 1 and t.a = cte.a
)
select *
from cte
order by a, b;
Here is a rextester.

how can I change where value in postgresql?

id o_num d_num
69af4bf986c4df522afb54da6512bdc5 5 5
69af6111de53b550b0d13f86398b59e5 19 19
69b264c4b93a1984450689b16807b293 10 10
69b26c0fb38ff1cd2d4b01696aa14883 20 20
69b5c46bdc8a8f49f913d9d2325f0a76 15 15
69b71276a69dece5630ed3405ceca411 1 6
69b790c7937602e8fd52bc4d28194625 5 17
69b7bfde4effdaf31d362165a23a8dd0 4 13
69b93626a799636aef2ab3567cf3a110 14 14
I have a table like this, there are total 20 o_num in the table, and i want to select all the row that o_num is 1 then group by the d_num to count the id number, and them change the o_num to 2, until o_num to 20. and the result is in one table.
here is my code for 1 time:
SELECT COUNT(id), o_num, d_num
FROM table1
WHERE o_num = 1
GROUP BY o_num, d_num
how can i change the code to get my table
I want get the reselt like this,a table with 3 columns
sum o_num d_num
9 1 1
8 1 2
4 1 3
……
5 1 20
4 2 1
6 2 2
8 2 3
……
3 2 20
5 3 1
……
……
2 20 20