Validate if exist before insert into another table - sql

I have to read a txt data that contains a first load that someone do, and insert data into 2 tables. this means:
At the begining tab_data and tab_list is empty.
with the first txt record, i have to validate first if "C43R" exist on "tab_list" table, if not, i have to insert and get the new ID, and after that insert that new ID created on "tab_data" table with the rest of information.
With the second record, first i have to validate if "C43R" exist on "tab_list" table, if exist i have to get the ID, and after that insert that new ID created on "tab_data" table with the rest of information.
with the fourth txt record, i have to validate first if "M23K" exist on "tab_list" table, if not, i have to insert and get the new ID, and after that insert that new ID created on "tab_data" table with the rest of information.
And the same with all the rows from the txt file.
So how can i start with this?
Does any body have a suggestion or a solution?
Really thanks, regards

You could do this with two queries. The logic would be to first feed tab_list, then tab_data. Note that you need an ordering column in txt_data for this to make sense - I assumed id.
This inserts into tab_list, while manually generating a sequence that starts at 10.
insert into tab_list(id, tab)
select tab_id, 9 + row_number() over(order by min(id))
from txt_data
group by tab_id
With this set-up at hand, you can then insert in tab_data:
insert into tab_data (id, tab_id, data)
select
99 + row_number() over(order by d.id),
l.id,
d.data
from txt_data d
inner join tab_list l on l.tab_id = d.tab_id

Related

Best approach to populate new tables in a database

I have a problem I have been working on the past several hours. It is complex (for me) and I don't expect someone to do it for me. I just need the right direction.
Problem: We had the tables (below) added to our database and I need to update them based off of data already in our DailyCosts table. The tricky part is that I need to take DailyCosts.Notes and move it to PurchaseOrder.PoNumber. Notes is where we currenlty have the PONumbers.
I started with the Insert below, testing it out on one WellID. This is Inserting records from our DailyCosts table to the new PurchaseOrder table:
Insert Into PurchaseOrder (PoNumber,WellId,JObID,ID)
Select Distinct Cast(Notes As nvarchar(20)), WellID, JOBID,
DailyCosts.DailyCostID
From DailyCosts
Where WellID = '24A-23'
It affected 1973 rows (The Notes are in Ntext)
However, I need to update the other new tables because we need to see the actual PONumbers in the application.
This next Insert is Inserting records from our DailyCost table and new PurchaseOrder table (from above) to a new table called PurchaseOrderDailyCost
Insert Into PurchaseOrderDailyCost (WellID, JobID, ReportNo, AccountCode, PurchaseOrderID,ID,DailyCostSeqNo, DailyCostID)
Select Distinct DailyCosts.WellID,DailyCosts.JobID,DailyCosts.ReportNo,DailyCosts.AccountCode,
PurchaseOrder.ID,NEWID(),0,DailyCosts.DailyCostID
From DailyCosts join
PurchaseOrder ON DailyCosts.WellID = PurchaseOrder.WellID
Where DailyCosts.WellID = '24A-23'
Unfortunately, this produces 3,892,729 records. The Notes field contains the same list of PONumbers each day. This is by design so that the people inputting the data out in the field can easily track their PO numbers. The new PONumber column that we are moving the Notes to would store just unique POnumbers. I modified the query by replacing NEWID() with DailyCostID and the Join to ON DailyCosts.DailyCostID = PurchaseOrder.ID
This affected 1973 rows the same as the first Insert.
The next Insert looks like this:
Insert Into PurchaseOrderAccount (WellID, JobID, PurchaseOrderID, ID, AccountCode)
Select PurchaseOrder.WellID, PurchaseOrder.JobID, PurchaseOrder.ID, PurchaseOrderDailyCost.DailyCostID,PurchaseOrderDailyCost.AccountCode
From PurchaseOrder Inner Join
PurchaseOrderDailyCost ON PurchaseOrder.ID = PurchaseOrderDailyCost.DailyCostID
Where PurchaseOrder.WellID = '24A-23'
The page in the application now shows the PONumbers in the correct column. Everything looks like I want it to.
Unfortunately, it slows down the application to an unacceptable level. I need to figure out how to either modify my Insert or delete duplicate records. The problem is that there are multiple foreign key constraints. I have some more information below for reference.
This shows the application after the inserts. These are all duplicate records that I am hoping to elminate
Here is some additional information I received from the vendor about the tables:
-- add a new purchase order
INSERT INTO PurchaseOrder
(WellID, JobID, ID, PONumber, Amount, Description)
VALUES ('MyWell', 'MyJob', NEWID(), 'PO444444', 500.0, 'A new Purchase Order')
-- link a purchase order with id 'A356FBF4-A19B-4466-9E5C-20C5FD0E95C3' to a DailyCost record with SeqNo 0 and AccountCode 'MyAccount'
INSERT INTO PurchaseOrderDailyCost
(WellID, JobID, ReportNo, AccountCode, DailyCostSeqNo, PurchaseOrderID, ID)
VALUES ('MyWell', 'MyJob', 4, 'MyAccount', 0, 'A356FBF4-A19B-4466-9E5C-20C5FD0E95C3', NEWID())
-- link a purchase order with id 'A356FBF4-A19B-4466-9E5C-20C5FD0E95C3' to an account code 'MyAccount'
-- (i.e. make it choosable from the DailyCost PO-column dropdown for any DailyCost record whose account code is 'MyAccount')
INSERT INTO PurchaseOrderAccount
(WellID, JobID, PurchaseOrderID, ID, AccountCode)
VALUES ('MyWell', 'MyJob', 'A356FBF4-A19B-4466-9E5C-20C5FD0E95C3', NEWID(), 'MyAccount')
-- link a purchase order with id 'A356FBF4-A19B-4466-9E5C-20C5FD0E95C3' to an AFE No. 'MyAFENo'
-- (same behavior as with the account codes above)
INSERT INTO PurchaseOrderAFE
(WellID, JobID, PurchaseOrderID, ID, AFENo)
VALUES ('MyWell', 'MyJob', 'A356FBF4-A19B-4466-9E5C-20C5FD0E95C3', NEWID(), 'MyAFENo')
So it turns out I missed some simple joining principles. The better I get the more silly mistakes I seem to make. Basically, on my very first insert, I did not include a Group By. Adding this took my INSERT from 1973 to 93. Then on my next insert, I joined DailyCosts.Notes on PurchaseOrder.PONumber since these are the only records from DailyCosts I needed. This was previously INSERT 2 on my question. From there basically, everything came together. Two steps forward an one step back. Thanks to everyone that responded to this.

Exclude a duplicate record from a view based on condtions and keep 1 - SQL Server 2012

I have three joined tables Student, StudentTransportOrder and Transport in SQL Server 2012.
I have created a StudentActivity view for this.
In the StudentTransportOrder table, each student record has a unique TransportOrderID.
When transport is ordered, VehicleID this is recorded into the StudentTransportOrder table.
Unfortunately the same VehicleID has been entered for the same date and time for a student records.
The StudentActivity view already returns records based on where conditions, but I also need to remove the duplicate records, preferably keep the records where if a student has used transport on the same date and time, that only one distinct VehicleID is returned and preferably the where the transport type is TransportVehicle = Car
How can I amend the view , without deleting records from the main tables, also bring back records even if no transport has been ordered
Please help
Append
ROW_NUMBER() OVER(PARTITION BY StudentID,VehicleID ORDER BY (SELECT NULL)) AS PartitionedCount
... to your query and use a filter like WHERE PartitionedCount=1.
This will number your rows for each combination of Student and vehicle separately (you'll have to include the date or datetime probably).
You can use the (ORDER BY (SELECT NULL)) to force a car sorted on top...
UPDATE
As I do not know your actual tables here's a general example:
DECLARE #tbl TABLE(ID INT IDENTITY,GroupID INT,SomeValue VARCHAR(100));
INSERT INTO #tbl(GroupID,SomeValue) VALUES
(1,'val 1 for 1')
,(1,'val 2 for 1')
,(1,'val 3 for 1')
,(2,'val 1 for 2')
,(2,'val 2 for 2')
,(3,'val 1 for 3')
,(3,'val 2 for 3');
WITH Numbered AS
(
SELECT tbl.*
,ROW_NUMBER() OVER(PARTITION BY GroupID ORDER BY ID /*DESC*/) AS Number
FROM #tbl AS tbl
)
SELECT * FROM Numbered
WHERE Number=1
Try first without the WHERE. You will get all rows with partitioned numbering. Using the WHERE will reduce the output to the one with number =1.
It is on you to find a clever ORDER BY which brings your cars to the top (CASE will help you probably).
Just good to know: In my ORDER BY you find an inactive DESC. If you take away the /**/ you can use the same approach to find the last row to a given sort order.

Oracle Database Trigger Selecting Previous Row

I am writing an AFTER INSERT Trigger on a table which is getting data from an Excel file, which has these three columns:
Tag_No ,Date ,Problem
The problem is that in this Excel File the Tag_No is not repeated when it is the same as the previous one. An example of this data is as follows:
Tag_No ,Date ,Problem
1 17-JUL-14 ABCS
18-JUL-14 asdf
2 17-JUL-14 ABCS
18-JUL-14 asdf
Tag_No will be empty if it is repeating like above. I would like to copy the above Tag_No for each row which I am inserting.
I would suggest solving this in a different way. Add an auto-incrementing column to the table. This will keep track of the order that the rows are put into the table. You can do this by defining a sequence and then using the sequence in the trigger.
Then, after the table is in the database, you can run an update to do what you want:
update table t
set tag = (select max(tag) keep (dense_rank first order by id desc)
from table t2
where t2.id < t.id and tag is not null
)
where tag is null;

Using output to capture auto increment identity, plus past identity mapping table

I am trying to make exact copies of data in SQL, with new clientIDs, but keep the existing data in the old client as well. I will be inserting the data into a table with an auto incrementing integer primary key ID. I need to retain the ID's of the Old records and the new records together so I can continue using this mapping as I copy the different table data so I can maintain relationships.
At this point I have the following:
INSERT INTO [dbo].[Driver]
OUTPUT inserted.ID
inserted.Name
inserted.ClientID
SELECT Name,
1234 AS clientID
FROM dbo.Driver
I am wondering if there is a way to also select the old ID of the driver in the Output so I can then insert all of this into a holding table using the OUTPUT. So I need to end up with the following after I perform the insert into the dbo.Driver table so I can also insert these values into a temp table:
NewID
OldID
Name
ClientID
At this point I don't know of a way to pull the Original ID from the original record.
I ended up using MERGE INTO to keep track of the old ID as per the following SO post:
How to use OUTPUT to capture new and old ID?
you can try...
INSERT INTO dbo.Driver (oldID, Name, clientID)
SELECT
B.ID,
A.Name,
1234 AS clientID
FROM dbo.Driver A
LEFT JOIN dbo.Driver B ON A.Name = B.Name AND A.clientID = b.clientID
or maybe just
INSERT INTO dbo.Driver (oldID, Name, clientID)
SELECT
ID,
Name,
1234 AS clientID
FROM dbo.Drive

Insert output IDs into another table

I have a status table, and another table containing additional data. My object IDs are the PK in the status table, so I need to insert those into the additional data table for each new row.
I need to insert a new row into my statusTable for each new listing, containing just constants.
declare #temp TABLE(listingID int)
insert into statusTable(status, date)
output Inserted.listingID into #temp
select 1, getdate()
from anotherImportedTable
This gets me enough new listing IDs to use.
I now need to insert the actual listing data into another table, and map each row to one of those listingIDs -
insert into listingExtraData(listingID, data)
select t.listingID, a.data
from #temp t, anotherImportedTable a
Now this obviously doesn't work, because otherDataTable and the IDs in #temp are unrelated... so I get far too many rows inserted.
How can I insert each row from anotherImportedTable into listingExtraData along with a unique newly created listingID? could I possibly trigger some more sql at the point I do the output in the first block of sql?
edit: thanks for the input so far, here's what the tables look like:
anotherImportedTable:
data
statusTable:
listingID (pk), status, date
listingExtraData:
data, listingID
You see that I only want to create one entry into statusTable per row in anotherImportedTable, then put one listingID with a row from anotherImportedTable into listingExtraData... I'm thinking that I might have to resort to a cursor perhaps?
Ok, here's how you can do it (if I'm right about what you actually want to do):
insert into listingExtraData(listingID, data)
select q1.listingID, q2.data
from
(select ListingID, ROW_NUMBER() OVER (order by ListingID) as rn from #temp t) as q1
inner join (select data, ROW_NUMBER() over (order by data) as rn from anotherImportedTable) q2 on q1.rn = q2.rn
In case you matching logic differs you will need to change sorting of anotherImportedTable. In case your match order can not be achieved by ordering anotherImportTable [in one way or another] then you're out of luck.