SQL update column depending on other column - sql

sequenceNo IsPoint PointNumber PointSequenceNumber IsCancel
1 1 3168 1 1
2 0 NULL 2 1
3 1 3169 2 1
4 1 2806 3 1
5 1 33322 4 1
6 1 2807 5 1
7 1 2044 6 1
8 1 2046 7 1
9 0 NULL 8 1
10 1 27524 8 1
11 1 670 9 0
12 1 671 10 0
13 1 672 11 0
14 0 NULL 12 1
15 1 1074 12 1
16 1 10844 13 0
17 1 1421 14 0
I need to insert PointNumber to other table depending on value of IsCancel Column if IsCancel is set to 1 I need to insert first iscancel and last IsCancel but sequentially
e.g. STARTPOINT => above sequenceNo 1 for point number 3168 and Iscancel set to 1 I need that point to store in other table StartPoint
ENDPOINT => above sequenceNo 15 for point number 1074 and Iscancel set to 1 I need that point to store in other table as Endpoint
TotalCANCELED => Column hold COUNT IsCancel but only if PointNumber is not NULL
I need to update these columns in other table with following numbers depending on above table
STARTPOINT ENDPOINT TOTALCANCEL
3168 1074 9
Thanks community

I find this logic a bit hard to follow. If I understand this correctly, you can use aggregation -- although you need a little twist to get the end point number:
select max(case when PointSequenceNumber = 1 then pointnumber end) as startpoint,
max(case when PointSequenceNumber = psn then pointnumber end) as endpoint,
sum(case when isCancel = 1 and PointNumber is not null end) as totalCancel
from (select t.*,
max(case when isCancel = 1 and PointNumber is not null then PointSequenceNumber end) over () as max_psn
from t
) t;

Related

Pairwise swapping of rows in sql

I have a device settings table with threshold types and values.
Let's say ThresholdType = 0 is Min and ThresholdType = 1 is Max
The initial table looks like this:
DeviceID ThresholdType ThresholdValue
1 0 5
1 1 10
2 0 15
2 1 20
3 0 21
3 1 34
4 0 1
4 1 8
Then I had to change ThresholdType meaning - 0 became Max threshold and 1 became Min one.
I want the table look like that:
DeviceID ThresholdType ThresholdValue
1 0 10
1 1 5
2 0 20
2 1 15
3 0 34
3 1 21
4 0 8
4 1 1
Is it possible to change update it with a single SQL without loops?
Update ThresholdType instead:
update tablename set ThresholdType = 1 - ThresholdType
In case other ThresholdType values might show up later, you can add WHERE ThresholdType IN (1, 2), to be a bit safer.
Just swap the ThresholdType:
UPDATE t SET ThresholdType = CASE ThresholdType
WHEN 1 THEN 0
WHEN 0 THEN 1
ELSE ThresholdType
END
Execute the query exactly once.
You can do:
update t
set ThresholdValue = (
select x.ThresholdValue
from t x
where x.DeviceID = t.DeviceID and x.ThresholdType <> t.ThresholdType
)
Result:
DeviceID ThresholdType ThresholdValue
--------- -------------- --------------
1 0 10
1 1 5
2 0 20
2 1 15
See running example at db<>fiddle.

oracle query with groupby clause

i have a upload table as follows:
bulk_upload_hist
id file_name doc_blob upload_date upload_by
10 abc.pdf 12-APR-21 123
11 xyz.pdf 12-APR-21 123
inventory history stores the records from the file as follows:
inventory_doc_hist
id upload_id upload_status create_date create_by inv_doc_type
1 10 1 12-APR-21 123 20
2 10 1 12-APR-21 123 20
3 10 0 12-APR-21 123 10
4 10 1 12-APR-21 123 10
4 11 1 12-APR-21 123 20
5 11 0 12-APR-21 123 10
I want my output per bulk upload as follows:
id file_name successful/10 Successful/20 UnSuccessful upload_date upload_by
10 abc.pdf 2 1 1 12-APR-21 123
11 xyz.pdf 1 1 0 12-APR-21 123
what is the best way to do this?
I think you want a join and conditional aggregation:
select buh.id, buh.file_name,
sum(case when ih.inv_doc_type = 10 then 1 else 0 end) as num_successful_10,
sum(case when ih.inv_doc_type = 20 then 1 else 0 end) as num_successful_20,
sum(case when ih.inv_doc_type not in (10, 20) then 1 else 0 end) as num_successful_20,
ih.upload_date, ih.upload_by
from bulk_upload_hist buh join
inventory_history ih
on ih.upload_id = ih.id
group by buh.id, buh.file_name, ih.upload_date, ih.upload_by;

How to add column in sql server with column name value is given by case expression

PriorityOID Priority NoOfRestrictedDaysForReporting AllowBackDatedCompletionForDays SOXReporting SortOrder PenaltyFactorPercent RiskFactor
1 Trifling NULL 0 NULL 50 105 3
2 Low NULL 0 NULL 40 105 3
3 Medium NULL 0 NULL 30 105 3
4 High NULL 0 NULL 20 105 3
5 Critical NULL 0 NULL 10 110 6
6 Not Available NULL 0 NULL 60 105 3
7 Super-critical NULL NULL NULL 9 120 9
I have to add one another column with name as 'Numbering' and case is when super then 1 when critical then 2 when high then 3 when medium then 4 when low then 5 when trifling then 6 when not available then 7
You can use a case expression:
select
t.*,
case priority
when 'Super' then 1
when 'Critical' then 2
when 'High' then 3
when 'Medium' then 4
when 'Low' then 5
when 'Trifling' then 6
when 'Not Available' then 7
end numbering
from mytable t
If you want to actually store that information in the table, then, as commented by Larnu, a computed column seems like a relevant approach (or a view):
alter table mytable
add numbering as (
case priority
when 'Super' then 1
when 'Critical' then 2
when 'High' then 3
when 'Medium' then 4
when 'Low' then 5
when 'Trifling' then 6
when 'Not Available' then 7
end
);
SELECT PriorityOID,Priority,NoOfRestrictedDaysForReporting,
AllowBackDatedCompletionForDays, SOXReporting,SortOrder,PenaltyFactorPercent,RiskFactor,
CASE WHEN Priority='super' THEN 1
WHEN Priority='critical' THEN 2
WHEN Priority='high' THEN 3
WHEN Priority='medium' THEN 4
WHEN Priority='low' THEN 5
WHEN Priority='trifling ' THEN 6
when Priority='Not Available' THEN 7
else 8....go on..
END AS Numbering
Frm YourTableName
Note:- You have to use case when then..

How to Interchange and update the order of rows in SQL?

I have a table called Device and now i need interchange the order of devid row for devid 5 and devid 6 .
CurrentTable
PID DEVID INID EVTYPEID EVID ALID PARMID TEXTID InputName Input2Name
1 1 0 30 0 100102 0 14 998-TCR1 998-EMG1
1 2 0 30 0 100103 0 15 998-FR 998-TCR2
9 3 0 30 0 100113 0 25 998-TCR2 998-EMG2
0 4 2 30 0 100114 0 26 998-FR NULL
8 5 18 4 53 100114 0 0 998-Sg op 998-Sg cl
4 6 17 4 53 1000114 0 0 SG_PB RA_PB
Expected Result
PID DEVID INID EVTYPEID EVID ALID PARMID TEXTID InputName Input2Name
1 1 0 30 0 100102 0 14 998-TCR1 998-EMG1
1 2 0 30 0 100103 0 15 998-FR 998-TCR2
9 3 0 30 0 100113 0 25 998-TCR2 998-EMG2
0 4 2 30 0 100114 0 26 998-FR NULL
4 6 17 4 53 1000114 0 0 SG_PB RA_PB
8 5 18 4 53 100114 0 0 998-Sg op 998-Sg cl
I do have 150 column in my table and PID and RID are Primary keys
your current select statement plus:
Order by case when DEVID = 6 then 5
when DEVID = 6 then 6
else Devid
end
Not a pretty solution but answers the question.
You need to use a temp number to switch them around.
UPDATE Device SET DEVID=-6 WHERE DEVID=6;
UPDATE Device SET DEVID=6 WHERE DEVID=5;
UPDATE Device SET DEVID=5 WHERE DEVID=-6;
If the other table has a foreign key relationship to the DEVID column then it gets a little trickier. Options:
You can break the foreign key relationship, make the switch, and then
put the key back.
You can create a temp record with DEVID=7 (or
something else not taken) and use 7 as your placeholder in the query
above (instead of -6). Don't forget in that case to delete your
dummy record when you're done.

sql query - selection of a correct row from a groups specified by id

id risk origin strength strength_sol
13456 1 1 3 3
13456 134 0 5 NULL
13456 128 0 7 NULL
13456 121 0 5 NULL
13456 122 0 4 NULL
13456 190 0 2 NULL
22367 1 1 5 5
22367 128 0 4 NULL
22367 1 0 2 NULL
22367 36 0 6 NULL
12789 1 1 5 5
12789 1 0 4 NULL
12789 118 1 2 NULL
12789 118 1 5 NULL
12789 1 0 7 NULL
16908 1 0 5 5
16908 36 0 4 NULL
16908 28 1 3 NULL
16908 128 1 5 NULL
16908 1 0 7 NULL
12439 1 0 4 4
12439 134 0 2 NULL
12439 16 0 5 NULL
15678 36 0 4 NULL
15678 28 0 2 NULL
15678 134 0 5 NULL
Problem and data description:
I have a big dataset. Above you can see just a small sample in order to describe my problem.
I need to choose exactly one row for each id.
In the dataset above there are all the possible cases that can happen.
The last two columns are not a part of the data set. They are the result that I need to get.
Origin is a 0/1 variable.
I need to choose this:
for one id:
situation: when risk = 1 and origin = 1 - Im ok, I will take this
row, there can be the only row like this for one id in the dataset
situation: when for one id there is no case that risk=1 and origin =1, I have to choose the row where risk=1 and origin = 0, if there are more such a rows, it doesn't matter which one I choose(But I have
to choose only ONE of them, not all of them).
when there in no risk = 1 in any row for one id (doesnt matter what is the value of the origin), I just simply put NULL as
strength_sol
My solution is like this (but it is not correct):
case when risk=1 and origin =1 then strength
when risk=1 and origin = 0 then strength
else NULL end as strength
This solution is not correct, because in the situation number one can happen that there is also a row with risk=1 and origin=0, but I'm not interested in that row (I want NULL for that row).
You can use the row_number function to number the rows so that the first row would be the one with highest priority (in this case risk=1 and origin=1) and the second with the next highest priority (risk=1 and origin=0). All the other rows are numbered arbitrarily and then you can choose the first row from each group.
select id,risk,origin,strength,
case when rnum=1 then strength end strength_sol
from (select t.*,
row_number() over(partition by id
order by case when risk=1 and origin =1 then 1
when risk=1 and origin =0 then 2
else 3 end) rnum
from t
) x
this is the final code :)
SELECT
id
,risk
,origin
,strength
,CASE
WHEN (X.rnum = 1 AND risk = 1) THEN strength
ELSE NULL
END AS strength_sol
FROM
(
SELECT
t.*
,ROW_NUMBER() OVER (
PARTITION BY id
ORDER BY CASE
WHEN risk = 1 AND
origin = 1 THEN 1
WHEN risk = 1 AND
origin = 0 THEN 2
ELSE 3
END
) rnum
FROM
t
) AS [X]