Create a new record based on multiple records - sql

I have a table with Accounts that, if there are multiple matching ones, I need to combine to create a new one in a procedure.
The table looks like:
ACCT ID QTY LEI
A_1 2 200 NULL
A_2 3 200 NULL
A_3 3 200 0
A_1 3 100 NULL
BB_1 2 200 NULL
BB_2 2 100 NULL
BB_3 3 200 0
BB_1 3 100 NULL
What I am trying to do is:
Find the ones I need to combine based on ACCT; The data above basically has two ACCTS, A and BB, the "_" are just to identify them as individual sub accounts.
For column QTY: SUM of QTY based on the ID and ACCT
For column LEI: If any record in the group of ACCT and ID is 0 and rest are NULL then replace with 0, if all are NULL then NULL
If there's only one record (no other record to merge with), that whole line will be used (see first record in table) .
Create a new record based on the above, rename ACCT to _X and delete the existing records it has used
End result of the above looks like this:
ACCT ID QTY LEI
A_X 2 200 NULL
A_X 3 500 0
BB_X 2 300 NULL
BB_X 3 300 0
Not sure what the best way of approaching this is, any ideas on this?

use string operations (like SubString and IndexOf) to parse the name of the account
use group by and aggregate functions (i.e. Sum) to calculate the results
insert the results into a temp table, delete the original data, insert back into the original table

Related

SELECT DISTINCT AND GET ALL VALUES FOR EACH COLUMN SQL ACCESS

I have a table that have grouped all samples returned from the lab analysis of my work.
The problem is that some labs send different elements via different files, and now I'm facing problems.
I need to make a query that grab all values that are stored in different columns and assign it in just one row for each sample. Example:
Batch Source_File Value Value 2
SAMPLE A 1 A 150 null
SAMPLE A 1 B null 100
SAMPLE B 2 C null 300
SAMPLE B 2 D 100 null
OUTPUT
Batch Source_File Value Value 2
SAMPLE A 1 A,B 150 100
SAMPLE B 2 C,D 100 300
You can use plain SQL:
SELECT
Samples.Sample,
Samples.Batch,
Min([Source_File]) & "," & Max([Source_File]) AS Source_Files,
Sum(Samples.Value) AS Sum1,
Sum(Samples.Value2) AS Sum2
FROM
Samples
GROUP BY
Samples.Sample,
Samples.Batch;
Output:

Oracle SQL - Need to eliminate data if at least one of the particular condition is not satisfied

My question is related to Oracle sql. I have a two tables say, study table and another one is study part table. Stdyno is the primary key in study table and (stydyno + sqncno) is the primary key in studypart table.
EG: studypart table has data as below.
studyNo sqnc part approvalIN
--------------------------------
123 1 fgh Y
123 2 jhf N
123 3 rty N
456 1 wer N
456 2 wdg N
456 3 ghg N
I need query in such a way that my output from studypart table gives result
as study number which has all the approvalIn as N. If it has at least one of the approvalIn as 'Y'
then that studyno should be excluded from the result.
Desired output:
studyno: 456
I tried this implementation in stored procedure taking Y and N approvalIn count separately ie,
if a studyno has both the count then exclude it and
if it has only one count say either N or Y the include it.
But i would like to know how to achieve this is query.
You can do it by excluding those rows whose count of "approvalIN = 'N'" does not match the total count of "approvalIN" values.
SELECT STUDYNO
FROM tab
GROUP BY STUDYNO
HAVING SUM(CASE WHEN approvalIN = 'N' THEN 1 END) = COUNT(approvalIN)
Check the demo here.

SQL - Update in a cross apply query

UPDATE Table1
SET SomeColumn = X.SomeOtherColumn
FROM Table1 T1
CROSS APPLY
(SELECT TOP 1 SomeOtherColumn
FROM Table2 T2
WHERE T2.SomeJoinColumn = T1.SomeJoinColumn
ORDER BY CounterColumn) AS X
I want to increase CounterColumn by 1 each time the cross apply query runs. Is there any way I could achieve this?
Some context and sample data
I have a table containing information about companies. I want to anonymize the company numbers in this table. To do this, I want to use data from another table, containing synthetized data. This table has a much smaller sample size. So I have to reuse the same synthetic companies multiple times. For each row in the table I anonymize, I want to pick a synthetic company of the same type. I want to use all the synthetic companies. That's where the counter comes in, counting how many times I've used that specific synthetic company. By sorting by this counter, I was hoping to be able to always pick the synthetic company that's been used the least.
Company table (Table1)
CompanyNumber
Type
67923
2
82034
2
90238
7
29378
2
92809
5
72890
2
Synthetic company table (Table2)
SyntheticCompanyNumber
Type
Counter
08366
5
0
12588
2
0
33823
2
0
27483
7
0
Expected output of Company table:
CompanyNumber
Type
12588
2
33823
2
27483
7
12588
2
08366
5
33823
2
Expected output of synthetic company table
SynteticCompanyNumber
Type
Counter
08366
5
1
12588
2
2
33823
2
2
27483
7
1

SQL - Update top n records for each value in column a where n = count of column b

I have one table with the following columns and sample values:
[test]
ID | Sample | Org | EmployeeNumber
1 100 6513241
2 200 3216542
3 300 5649841
4 100 9879871
5 200 6546548
6 100 1116594
My example count query based on [test] returns these sample values grouped by Org:
Org | Count of EmployeeNumber
100 3
200 2
300 1
My question is can I use this count to update test.Sample to 'x' for the top 3 records of Org 100, the top 2 records of Org 200, and the top 1 record of Org 300? It does not matter which records are updated, as long as the number of records updated for the Org = the count of EmployeeNumber.
I realize that I could just update all records in this example but I have 175 Orgs and 900,000 records and my real count query includes an iif that only returns a partial count based on other columns.
The db that I am taking over uses a recordset and loop to update. I am trying to write this in one SQL update statement. I have tried several variations of nested select statements but can't quite figure it out. Any help would save my brain from exploding. Thanks!
Assuming, that id is the unique ID of the row, you could use a correlated subquery to select the count of row IDs of the rows sharing the current organization, that are less than or equal to the current row ID and check, that this count is less than or equal to the number of records from that organization you want to designate.
For example to mark 3 records of the organization 100 you could use:
UPDATE test
SET sample = 'x'
WHERE org = 100
AND (SELECT count(*)
FROM test t
WHERE t.org = test.org
AND t.id <= test.id) <= 3;
And analog for the other cases.
(Disclaimer: I don't have access to Access (ha, ha, pun), so I could not test it. But I guess it's basic enough, to work in almost every DBMS, also in Access.)

Count duplicates in an internal table?

I just want to ask on how to count duplicates in an internal table. I wanted to this in order for me to count per customer and put it into the Customer count column.
Sales Employee Customer Customer Count
a 1 2
a 2 2
b 3 3
b 2 3
b 4 3
c 1 1
as suncatcher mentions in his comment, using sql aggregates is more efficient than looping through internal tables. But if that is not possible in your case, one way would be to use the collect statement. collect adds entries to an internal table and adds up numerical fields when a row with the same key fields already exists. Create an internal table with a field for your sales employee, another field for the count and loop through your sales table, using collect to update your count table for each sale.
types: begin of t_count,
employee type text10,
count type i,
end of t_count.
data: it_count type standard table of t_count,
wa_count type t_count.
loop at it_sales into wa_sales.
move: wa_sales-employee to wa_count-employee,
1 to wa_count-count.
collect wa_count into it_count.
endloop.
The example assumes you have a table it_sales, a work area wa_sales, both with a field employee. Table it_count then contains a list of your employees (in the order they appear in your sales table) and the number of times they appeared in the sales table.
FIELD-SYMBOLS : <lfs_sales> TYPE ty_sales.
Assuming li_sales is an internal table with columns Sales_employee, Customer and customer_count. Initially the table entries are present as follows.
Sales_employee Customer customer_count
a 1 0
a 2 0
b 3 0
b 2 0
b 4 0
c 1 0
We need to calculate the duplicate sales_employee count and update the customer_count field. We can make use of collect statement as suggested by Dirik or make use of control break statements as shown below.
Prerequisite to make use of SUM keyword is to initialize the customer_count as 1 in each row so that it can sum up the customer count based on similar sales_employee.
LOOP AT li_sales ASSIGNING <lfs_sales>.
<lfs_sales>-customer_count = 1.
ENDLOOP.
Now the entries look as shown below.
Sales_employee Customer customer_count
a 1 1
a 2 1
b 3 1
b 2 1
b 4 1
c 1 1
Following code does update the customer_count field value.
LOOP AT li_sales INTO rec_sales.
AT END OF employee.
SUM.
MOVE-CORRESPONDING rec_sales TO rec_count.
APPEND rec_count TO li_count.
CLEAR rec_count.
ENDAT.
ENDLOOP.
SORT li_count BY employee.
LOOP AT li_sales ASSIGNING <lfs_sales>.
CLEAR rec_count.
READ TABLE li_count INTO rec_count
WITH KEY employee = <lfs_sales>-employee
BINARY SEARCH.
IF sy-subrc IS INITIAL.
<lfs_sales>-count = rec_count-count.
ENDIF.
ENDLOOP.
Now the internal table gets assigned with customer_count as below.
Sales_employee Customer customer_count
a 1 2
a 2 2
b 3 3
b 2 3
b 4 3
c 1 1