oracle query to get count of added, updated and deleted records based on the date filter - sql

I have a table structure like below
ID OLDID col1 status
1 0 txt1 A - inserted record
2 0 txt1 I - deleted record
3 0 txt1 I - updated record
4 3 txt1 I - updated record
5 4 txt1 I - updated record
6 5 txt1 I - deleted record
7 0 txtx I - updated record
8 7 txt1 A - updated record
I wanted to count the inserted, updated and deleted record in this table, please help me with the oracle query to fetch the count of the records, below are the logic
The logic for new record is ID is new ID and old id is 0 and status is A.
The updated record's status is I, the id of this record will be inserted into the new record's old id column.
the deleted record status with I with old id 0, and the second condition is status is I and ID will not be in OLD id column.
I have tried my best to explain the case, please let me know if any more details are needed. help me with the oracle query.
below query seems to be working, but if no deleted record then I wanted to have 0 for it but in the below query only returns records which have >0 counts, can any expert optimize it, please
SELECT sub.status, COUNT(*)
FROM (SELECT CASE
WHEN yt.oldid = 0 AND yt.status = 'A' THEN 'Insert'
WHEN yt.status = 'I' and QID not in (select oldid from FROM your_table where TO_CHAR (record_date,'MM/YYYY')='04/2020' ) THEN 'Delete'
ELSE 'Update' END AS status
FROM your_table yt where TO_CHAR (record_date,'MM/YYYY')='04/2020')
GROUP BY sub.status;
Neep experts help here, please.

You can use CASE..WHEN and self LEFT JOIN as follows:
SELECT T.*,
CASE WHEN T.OLDID = 0 AND T.STATUS = 'A' THEN 'Insert'
WHEN T.STATUS = 'I' AND T1.ID IS NOT NULL THEN 'Update'
WHEN T.STATUS = 'I' AND T.OLDID = 0 AND T1.ID IS NULL THEN 'Delete'
END AS RECORD_OP
FROM YOUR_TABLE T
LEFT JOIN YOUR_TABLE T1 ON T.ID = T1.OLDID

Related

Get a particular record based on a condition in SQL

My requirement is to get id for missing status from SQL table. I will get a list of status for each id, say A,B,C,D. In a scenario, I have to check status B exists or not. Table gets updated everyday and each time new Id will be created
Conditions,
If status A exists and other statuses such as C and D does not
exists, then don't need to get id.
If status A and B exists and other statuses such as C or D does not exists, then don't need to get id .
If status A exists and B not exists, other
statuses such as C or D exists, then I should get the id of that
record
If status A and B exists, other
statuses such as C or D exists (all status exists), then I don't need to get the id of that
record
Table1:
Id StatusCode
1 A
1 C
2 A
2 B
2 C
3 A
3 C
3 D
How do I get Id 1 and 3 using SQL query?, Seems simple but as I am new to SQL I could not able to get it in SQL.
select statement in this screenshot works fine when there is only one id, it fails on multiple id. I tried many other way, but no use
Try this
SELECT DISTINCT ID
FROM T1
WHERE Statuscode = 'A' AND ID NOT IN (SELECT ID FROM T1 WHERE Statuscode = 'B' )
AND (ID IN (SELECT ID FROM T1 WHERE Statuscode = 'C' ) OR ID IN (SELECT ID FROM T1 WHERE Statuscode = 'D' ))
FIDDLE DEMO
Also, To correct Gordon Linoff's answer, we need to add one more where criteria there
SELECT Id
FROM T1
GROUP BY Id
HAVING SUM(CASE WHEN Statuscode = 'A' THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN Statuscode = 'B' THEN 1 ELSE 0 END) = 0 AND
SUM(CASE WHEN Statuscode IN ('C', 'D') THEN 1 ELSE 0 END) > 0;
FIDDLE DEMO
This answers the original version of the question.
I think you can use aggregation:
select id
from t
group by id
having sum(case when status = 'A' then 1 else 0 end) > 0 and
sum(case when status in ('C', 'D') then 1 else 0 end) > 0;
SELECT id
FROM t
GROUP BY
Id
HAVING MAX(status) = CHAR(64 + COUNT(*))
--char(64+1) = A, char(64+2) = B etc
The logic behind this is that it will take all count the same types of id. So if you have 3 rows you will need abc. If you have an id with 4 rows you will have ABCD. Generally the max status should always be the same as the number of rows.
This is true of course if you have no duplicate between id and status code.
select distinct id from t where t.statuscode = 'C' or t.statuscode = 'D' group by t.id

I'm trying to take a record from, for example row 1 and insert it into row 3

I have a field called RecordType that has three different records, 1, 2, 3. Each hold different records. I want to take the the balance from another field I have called Limit from RecordType 1 and insert it into RecordType 3 but I'm just unsure on how to do this. This will be going into a Crystal Report and I want to be able to suppress the RecordType 1 altogether.
I've tried a simple case statement but that's about it, I can't really think of any other ways to do it (I'm sure there's loads).
CASE
WHEN FA.RecordType = 3 THEN
FA.Limit
END AS LimitTest
Current results
Record Type
Limit
1
5,000,301
2
0
3
0
Expected Results
Record Type
Limit
2
0
3
5,000,301
You seem to want to combine the limit for types 1 and 3. You can do this with aggregation on an expression:
select (case when recordtype = 1 then 3 else recordtype end) as recordtype,
sum(limit) as limit
from t
group by (case when recordtype = 1 then 3 else recordtype end);
You can try using sub-query and a Case statement in your select statement, for example:
SELECT [RecordType],
(CASE [RECORDTYPE] WHEN 3 THEN
(SELECT LIMIT from Table_1 WHERE RECORDTYPE = 1)
ELSE LIMIT END) LimitTest
FROM TABLE_1 WHERE RECORDTYPE <> 1
You said:
Sorry my formatting is terrible I'm not sure how to do it properly. But to answer your question no type 1 & 3 will never have the same value as 3 never has a value. I want to basically move the value from type 1 into type 3
Which makes me think that this would be the simplest:
DELETE FROM table WHERE RecordType = 3
UPDATE table SET RecordType = 3 WHERE RecordType = 1
3 never has a value so let's get rid of them first, then 1 has the value but we want it to be 3 so just update all the 1s to be 3s instead
If you're not into deleting it, just mask it instead:
SELECT 3 as RecordType, Limit FROM table WHERE RecordType = 1
If you want to move value from type 1 to type 3 then do simple update in your query.
update t set t.value= t1.value from table as t , table as t1 where t.recordtype=3 and t1.recordtype=1
or
delete from table where recordtype = 3
update recordtype set recordtype=1 where recordtype=3
This will work may be
SELECT
IIF(A.RECORDTYPE = 1,3,A.RECORDTYPE) AS RECORDTYPE,
A.LIMIT
FROM
(
SELECT 1 RECORDTYPE,5000301 LIMIT UNION ALL
SELECT 2 RECORDTYPE,0 LIMIT UNION ALL
SELECT 3 RECORDTYPE,0 LIMIT
) A
WHERE A.RECORDTYPE IN (1,2)
ORDER BY RECORDTYPE
Check this if works for you.

Update column in table depending on table data

I am working on a table on SQL where I need to fill in a new column depending on the value of 2 other columns in the table.
The rules are:
- New column = 1 if Row id = 1 and the group id for that row has more rows with the same group id (See pic)
- New column = 2 if Row id >= 2
- Anything else will make the new column 0
Table
This is my query to update the new column which works:
UPDATE t1 SET t1.New_Column = CASE WHEN t1.RowID >= 2 THEN 2
ELSE CASE WHEN t1.RowID = 1 and (SELECT count(*) FROM dbo.__test1 as t2 WHERE t2.GroupID = t1.GroupID) > 1
THEN 1 ELSE 0 END END from dbo.__test1 as t1
The end table result(Correct):
I want to know if there is a better and more efficient way of updating the new column as I feel calling the table within the select to count the number of group id's doesn't seem right?
Thanks
It will be faster to get the counts at the table level instead of row.
Removed one level of your CASE expression too - that probably won't change anything but it's a little cleaner to my eyes.
UPDATE t
SET t.NewColumn = CASE WHEN t2.RowID >=2 THEN 2
WHEN t2.RowID = 1 AND cnt > 1 THEN 1
ELSE 0
END
FROM dbo.__test1 t
JOIN (SELECT GroupID, COUNT(*) cnt
FROM dbo.__test1
GROUP BY GroupID) t2 on t.GroupID = t2.GroupID

SQL Query. Converted records seen in a row

If I have the following data layout seen below how could I return a query to switch the 'InforceInd' records displaying as '0' to '1'? (As long as 1 'policynumber' record contains a 'InforceInd' record of '1' switch all remaining rows from '0' to '1'?)
COLUMNS - PolicyNumber, InforceInd
ROW - XYZ, 1
ROW - XYZ, 0
ROW - XYZ, 0
Thank you in advance.
Try:
UPDATE MyTable
SET InforceInd = 1
WHERE
InforceInd = 0
AND
PolicyNumber IN (
SELECT PolicyNumber FROM MyTable WHERE InforceInd = 1);

oracle sql - compare row 1 and two, show results in row 3?

My table holds type 2 change history; so if recordID 123 has a change made by a user, then 'latest_effective' gets set to FALSE and the newly created record with recordID 123 has 'latest_effective' set to TRUE.
I'm looking for a query that returns the new record & the record that was just changed with a third row that is TRUE if there is a change in that column and FALSE if not.
select RecordID,1 latest_effective,Column1,Column2, etc...
from YourTable
where latest_effective = 1
union all
select RecordID,0 latest_effective,Column1,Column2, etc...
from YourTable
where latest_effective = 0
union all
select t.RecordID,-1 latest_effective,
case t.Column1 when f.Column1 then 'FALSE' else 'TRUE' end AS Column1
case t.Column2 when f.Column2 then 'FALSE' else 'TRUE' end AS Column2, etc...
from YourTable AS t
inner join YourTable AS f
on f.RecordID = t.RecordID
and f.latest_effective = 0
where t.latest_effective = 1
order by RecordID,latest_effective desc