Check if condition is true and if so add value to another column in sql - sql

I have a postgres table that looks like this:
A B
5 4
10 10
13 15
100 250
20 Null
Using SQL, I would like to check whether the value in column A is larger than the value in column B and if so, then add a 1 to the column True. If the value in column A is smaller or equal to the value in column B or if column B contains a [NULL] value, I would like to add a 1 to the column False, like so:
A B True False
5 4 1 0
10 10 0 1
13 15 0 1
100 25 1 0
20 [NULL] 0 1
What is the best way to achieve this?

You can use case logic:
select t.*,
(case when A > B then 1 else 0 end) as true_col,
(case when A > B then 0 else 1 end) as false_col
from t;

Related

How to check pair of string values in a column, after grouping the dataframe using ID column?

My Doubt in a Table/Dataframe viewI have a dataframe containing 2 columns: ID and Code.
ID Code Flag
1 A 0
1 C 1
1 B 1
2 A 0
2 B 1
3 A 0
4 C 0
Within each ID, if Code 'A' exists with 'B' or 'C', then it should flag 1.
I tried Groupby('ID') with filter(). but it is not showing the perfect result. Could anyone please help ?
You can do the following:
First use pd.groupby('ID') and concatenate the codes using 'sum' to create a new column. Then assing the value 1 if a row contains A or B as Code and when the new column contains an A:
df['s'] = df.groupby('ID').Code.transform('sum')
df['Flag'] = 0
df.loc[((df.Code == 'B') | (df.Code == 'C')) & df.s.str.contains('A'), 'Flag'] = 1
df = df.drop(columns = 's')
Output:
ID Code Flag
0 1 A 0
1 1 C 1
2 1 B 1
3 2 A 0
4 2 B 1
5 3 A 0
6 4 C 0
You can use boolean masks, direct for B/C, per group for A, then combine them and convert to integer:
# is the Code a B or C?
m1 = df['Code'].isin(['B', 'C'])
# is there also a A in the same group?
m2 = df['Code'].eq('A').groupby(df['ID']).transform('any')
# if both are True, flag 1
df['Flag'] = (m1&m2).astype(int)
Output:
ID Code Flag
0 1 A 0
1 1 C 1
2 1 B 1
3 2 A 0
4 2 B 1
5 3 A 0
6 4 C 0

Creating 2 "cartridges" of cumulative sum with conditions using SQL

I need to create 2 cumulative sums based on the value type, for example:
I have values of incoming stock units from 2 types: A and B. and I also have records of outgoing stock units.
If we have enough stock of type "A" it should taken out of type A, if not- it should be taken out of type B. so basically I need to crate the columns "A stock" and "B stock" below, representing the current balance of each type.
I tried using cumulative sum but I'm having trouble with the condition... is there a way to write this query without using a loop ? ( Vertica DB)
In table below A_stock and B_stock are the final result I need to create
ID Type In OUT A stock B stock Order_id
1 A 100 0 100 0 1
1 B 50 0 100 50 2
1 A 100 0 200 50 3
1 - 0 -200 0 50 4
1 - 0 -10 0 40 5
1 B 50 0 0 90 6
1 A 40 0 40 90 7
1 - 0 -20 20 90 8
2 A 30 0 30 0 1
2 B 20 0 30 20 2
2 A 10 0 40 20 3
2 - 0 -20 20 20 4
You can use window functions - but you need a column that defines the ordering of the rows, I assumed ordering_id:
select t.*,
sum(case when type = 'A' then in + out else 0 end) over(partition by id order by ordering_id) a_stock,
sum(case when type = 'B' then in + out else 0 end) over(partition by id order by ordering_id) b_stock
from mytable t
This assumes that you want the stock on a per-id basis; if that's not the case, just remove the partition clause from the over() clause.

Updating multiple columns based on multiple conditions

I've below table with some results for both Morning and Afternoon session (for different periods).
I would like to updated the results based on the simple condition:
Check if in 2 following morning sessions there was a change - if not add 5 to the score:
Example: ID=1, Mor2=C, Mor3=C so Score_M3 = 5+5= 10 (new value). All updated values are marked in the 'Wanted' table.
How can I write this in SQL? I will have a lot of columns and IDs.
My dataset:
ID Mor1 Aft1 Mor2 Aft2 Mor3 Aft3 Score_M1 Score_A1 Score_M2 Score_A2 Score_M3 Score_A3
1 A A C B C B 1 1 1 1 5 6
2 C C C B C B 1 1 1 1 4 5
3 A A A A A A 1 1 1 1 4 1
Wanted :
ID Mor1 Aft1 Mor2 Aft2 Mor3 Aft3 Score_M1 Score_A1 Score_M2 Score_A2 Score_M3 Score_A3
1 A A C B C B 1 1 1 1 *10 6
2 C C C B C B 1 1 *6 1 *9 5
3 A A A A A A 1 1 *6 1 *9 1
Here is the SQL to get you started. You can add many more columns as you see fit.
Can we restate as SAME, rather than Change?
If Mor1 = Mor2 then add +5 to Score2
If Mor2 = Mor3 then add +5 to Score3
UPDATE [StackOver].[dbo].[UpdateMultiCols]
SET
[Score_M1] = Score_M1
,[Score_M2] = Score_M2 +
Case When Mor1 = Mor2 Then 5 else 0 End
,[Score_M3] = Score_M3 +
Case When Mor2 = Mor3 Then 5 else 0 End
GO

SQL order by 0 first and then descend number/values

I have a weird situation where i need to order 0 first and then descends a column.
Let's say i have column that looks like this
Status
------
3
4
0
5
1
2
4
0
2
And Now i need to order it by
Status
------
0
0
5
4
4
3
2
2
1
Is this possible for SQL? I've been trying to test for 2 days now but i am stuck.
Use a case expression to first sort 0's and then the rest. After that sort by status desc:
order by case when Status = 0 then 0 else 1 end, status desc

SQL Server 2012 if one of the columns contain 1 function

I am trying to figure how I could do this where I have a table as follows:
ID FKeyID Complete
1 6 1
2 6 0
3 6 0
4 7 0
5 8 0
6 8 0
I want to create a function to return 1 or true if any FKeyID for example 6 has a value of 1 in complete column and 0 if it does not.
This is a function that takes fKey value and should return 1 or 0 based on that.
So in above basically if my FKeyID is 6 return 1 because complete column is 1 in one of the rows, and 0 for FKeyID 8 because none of values in column complete is 1.
CREATE function [dbo].f_x
(
#FKeyID int
)
RETURNS bit
as
begin
return case when exists
(select 1 from test where Complete = 1 and FKeyID = #FKeyID)
then 1 else 0 end
end