How to select a Algokey when [ UserSelect] column has any of row value is 1 otherwise switch to[ SytemSelect]column haivng row value is 1 - sql

I have a table with Scenario,Product,AlgoKey,User Select,System Select columns, I have to select the algo key for each scenario, The first priority goes to user selected otherwise system selected.
I have Shared my Inout & output result below, could you please help me how to write query for this.
Scenario
Product
AlgoKey
User Select
SystemSelect
1
P101
1
0
1
1
P102
2
1
0
2
P101
1
0
1
2
P102
2
0
0
3
P101
1
1
1
3
P102
2
0
0
4
P101
1
0
0
4
P102
2
0
1
OutPut :
Scenario
AlgoKey
Columnselected
1
2
User
2
1
System
3
1
User
4
2
System

here is how you can do it
select scenario , AlgoKey, case when Userselect = 1 then 'User' else 'System' end Columnselected
from (
select *, ROW_NUMBER() over (partition by scenario,productkey order by userselect desc, systemselect desc) rn
from tableName
) t
where rn = 1

Related

How to reset running counts and start from 1 based on the condition and make previous row values as 0 in SQL?

For example there is some table with below data:
No Id Value
1 100 1
2 100 0
3 100 1
4 100 2
1 101 1
2 101 2
1 102 0
2 102 1
I have to write SQL query, which will return row count based on specific condition. If the value matches 0 then need to reset running counts and start from 1 and make previous row values as 0
So the result will be like:
No Id Value Running Count
1 100 1 0
2 100 0 0
3 100 1 1
4 100 1 2
1 101 1 1
2 101 2 2
1 102 1 0
2 102 0 0
Your sample dataset is quite limited so I'm not sure of all edge cases but see if the following works for you. If not it might help get you there.
This gets a running count using a window & case expression and uses lead to check the next value.
If the current value or next value is 0 the count is 0, otherwise it's the running count subtracting 1 if there is a 0 in the Id block indicating the count was reset.
select No, Id, Value,
case when value = 0 or nv = 0
then 0
else
rc - case when Min(value) over(partition by id) = 0 then 1 else 0 end
end Running_Count
from (
select *,
Sum(case when value = 0 then 0 else 1 end) over(partition by id order by no) rc,
Lead(Value) over(partition by Id order by No)nv
from t
)t;

How to get the data with a condition for other table?

My query:
SELECT skill_code FROM TableSkills
I have tables TableSkills and TableUsers. How can I achieve skill_code data that only shows the skill_code if the user from TableUsers has at least "1"?
Expected result :
skill_code
Skill_1
Skill_2
Skill_3
Skill_6
TableSkills :
ID
skill_code
1
Skill 1
2
Skill 2
3
Skill 3
4
Skill 4
5
Skill 5
6
Skill 6
TableUsers :
ID
User
Skill_1
Skill_2
Skill_3
Skill_4
Skill_5
Skill_6
1
Mark
1
1
0
0
0
0
2
John
0
0
1
0
0
0
3
Doe
0
1
1
0
0
0
4
Jason
1
1
0
0
0
0
5
Kevin
1
1
0
0
0
0
6
Mike
0
1
1
0
0
1
Join the tables with a CASE expression in the ON clause:
SELECT DISTINCT s.skill_code
FROM TableSkills s INNER JOIN TableUsers u
ON 1 = CASE s.ID
WHEN 1 THEN u.Skill_1
WHEN 2 THEN u.Skill_2
WHEN 3 THEN u.Skill_3
WHEN 4 THEN u.Skill_4
WHEN 5 THEN u.Skill_5
WHEN 6 THEN u.Skill_6
END;
Or, with EXISTS, which may perform better:
SELECT s.skill_code
FROM TableSkills s
WHERE EXISTS (
SELECT *
FROM TableUsers u
WHERE 1 = CASE s.ID
WHEN 1 THEN u.Skill_1
WHEN 2 THEN u.Skill_2
WHEN 3 THEN u.Skill_3
WHEN 4 THEN u.Skill_4
WHEN 5 THEN u.Skill_5
WHEN 6 THEN u.Skill_6
END
);
See the demo.

Number of Rows Between Polarity Changes SQL

I want to count the number of rows between polarity changes grouped by id in SQL. I'm thinking that there may be a clever way to use window functions to get the job done but I don't know what it is.
Consider data like this:
id
polarity
date
1
0
12/1
1
1
12/2
1
0
12/3
1
0
12/4
1
1
12/5
2
0
12/1
2
0
12/2
2
0
12/3
2
1
12/4
2
0
12/5
2
0
12/6
2
0
12/7
2
1
12/8
Is there a way to count the number of rows between each change in polarity to get something like this :
id
n
1
1
1
2
2
3
2
3
You can do:
select id, count(*) as n
from (
select *,
sum(i) over(partition by id order by date) as g
from (
select *, case when polarity <> lag(polarity)
over(partition by id order by date)
then 1 else 0 end as i
from t
) x
) y
group by id, g
having max(polarity) = 0

case when... for subgroups

I have table like this:
receipt
position
unit
booking time
1
1
1
08:00:00
1
2
1
08:00:05
1
3
1
08:00:11
1
4
1
08:00:18
1
5
1
08:00:21
1
6
5
08:00:25
1
1
1
08:00:30
1
2
1
08:00:33
1
3
1
08:00:37
1
4
1
08:00:40
1
5
1
08:00:49
2
1
1
08:01:55
2
2
1
08:01:58
2
3
1
08:02:04
3
1
1
08:02:20
3
2
5
08:02:24
3
1
1
08:02:30
3
2
1
08:02:35
I want to check for every receipt whether unit 5 exists or not. If unit 5 exists, I only want to select positions with a booking time after the entry with unit 5.
For the example above my result therefore should look like this:
receipt
position
unit
bookingtime
1
1
1
08:00:30
1
2
1
08:00:33
1
3
1
08:00:37
1
4
1
08:00:40
1
5
1
08:00:49
2
1
1
08:01:55
2
2
1
08:01:58
2
3
1
08:02:04
3
1
1
08:02:30
3
2
1
08:02:35
I have kind of a start, which delivers the right result if there was only one receipt:
Select * from test
where bookingtime> (case
when (select Max(bookingtime) from test where unit=5) is null
then (Select convert(time,'00:00:00'))
Else (select Max(bookingtime) from testdb where unit=5)
End)
What am I missing to let this code run through every single receipt separately so that I get the result I am looking for?
You can use a window function to get the time for unit 5:
select t.*
from (select t.*,
min(case when unit = 5 then bookingtime end) over (partition by receipt) as bookingtime_5
from t
) t
where bookingtime_5 is null or
bookingtime > bookingtime_5;

SQL Query. limit an update per rows if condition is X and Y for the same ID number

Have the following table tblTrans where
Trans_ID Trans Sequence Trans_PointsEarned Trans_PointsApplied
4452 1 1 1
4452 2 1 1
4452 3 0 1
4462 1 1 1
4462 2 1 1
4462 3 1 1
4462 4 1 1
4462 5 1 1
9101 1 0 1
9101 2 0 1
9101 3 0 1
9101 4 0 1
(useless table doesnt work)
I need to set the following on another field per every customer ID.
So Customer_OverallPoints
4452 = 2 (doesn't count 0's)
4462 = 4 (I want to cap the points to 4 based on the sequence and transID and customerID)
9101 = 0 (dont count 0's).
This needs to be applied to thousands of records based on customerID and TransID where Trans_Sequence is within the same Trans_ID and it only counts the first 4 rows that have the Trans_pointsEarned = 1.
I tried putting a psuedocode together but it just looked ridicilous and I can't even come up with the logic for this.
Thanks
Assuming that TransId is really the customer id, I think the basic logic is just an aggregation:
select t.TransId,
(case when sum(t.Trans_PointsEarned) > 4 then 4
else sum(t.Trans_PointsEarned)
end) as Customer_OverallPoints
from tblTrans t
group by t.TransId;
You can put this into an update statement as:
update customers c
set Customer_OverallPoints = (select (case when sum(t.Trans_PointsEarned) > 4 then 4
else sum(t.Trans_PointsEarned)
end)
from tblTrans t
where t.TransId = c.CustomerId
);