TSQL Inserting records and track ID - sql

I would like to insert records in a table below (structure of table with example data). I have to use TSQL to achieve this:
MasterCategoryID MasterCategoryDesc SubCategoryDesc SubCategoryID
1 Housing Elderly 4
1 Housing Adult 5
1 Housing Child 6
2 Car Engine 7
2 Car Engine 7
2 Car Window 8
3 Shop owner 9
So for example if I enter in a new record with MasterCategoryDesc = 'Town' it will insert '4' in MasterCategoryID with the respective SubCategoryDesc + ID.
CAN I SIMPLIFY THIS QUESTION BY REMOVING THE SubCategoryDesc and SubCategoryID columns. How can I achieve this now just with the 2 columns MasterCategoryID and MasterCategoryDesc

INSERT into Table1
([MasterCategoryID], [MasterCategoryDesc], [SubCategoryDesc], [SubCategoryID])
select TOP 1
case when 'Town' not in (select [MasterCategoryDesc] from Table1)
then (select max([MasterCategoryID])+1 from Table1)
else (select [MasterCategoryID] from Table1 where [MasterCategoryDesc]='Town')
end as [MasterCategoryID]
,'Town' as [MasterCategoryDesc]
,'owner' as [SubCategoryDesc]
,case when 'owner' not in (select [SubCategoryDesc] from Table1)
then (select max([SubCategoryID])+1 from Table1)
else (select [SubCategoryID] from Table1 where [SubCategoryDesc]='owner')
end as [SubCategoryID]
from Table1
SQL FIDDLE
If you want i can create a SP too. But you said you want an T-SQL

This will take three steps, preferably in a single Stored Procedure. Make sure it's within a transaction.
a) Check if the MasterCategoryDesc you are trying to insert already exists. If so, take its ID. If not, find the highest MasterCategoryID, increase by one, and save it to a variable.
b) The same with SubCategoryDesc and SubCategoryID.
c) Insert the new record with the two variables you created in steps a and b.

Create a table for the MasterCategory and a table for the SubCategory. Make an ___ID column for each one that is identity (1,1). When loading, insert new rows for nonexistent values and then look up existing values for the INSERT.
Messing around with finding the Max and looking up data in the existing table is, in my opinion, a recipe for failure.

Related

How can I use an input from another table in my query?

I'm creating a new table using PostgreSQL, but I need to get a parameter from another table as an input.
This is the table I have (I called table_1):
id column_1
1 100
2 100
3 100
4 100
5 100
I want to create a new table, but only using ids that are higher than the highest id from the table above (table_1). Something like this:
insert into table_new
select id, column_1 from table_old
where id > (max(id) from table_1)
How can I do this? I tried searching, but I got to several posts like https://community.powerbi.com/t5/Desktop/M-Query-Create-a-table-using-input-from-another-table/td-p/209923, Take one table as input and output using another table BigQuery and sql query needs input from another table, which are not exactly what I need.
Just use where id > (select max(id) from table_1).

acessing columns relevant to dynamic table in oracle

i have been having trouble solving what seems to me a complex aspect of plsql, I have a table1 with a list of table_names and a table2 with backups to those table_names
Table1
id name max_rows date
1 a 100 2018-10-06
2 b 100 2018-10-06
3 c 100 2018-10-06
Table2
id name_bck FK date_created date closed
1 a_bck 1
2 b_bck 2
3 c_bck 3
so the idea is for me to insert rows from a onto a_bck until a_bck reaches its limit (max_rows) then i would create a new a_bck2 and close(update close date from table2);
the problem im having is i cant access columns from table a of my table1, i want to insert data from a to a_bck where its date column from table a is < then sysdate
so i created 2 cursors to go through both tables and return the data i need to perform operations over.
cursor c1 is
select id name max_rows from table1 where date<sysdate;
curso2 c2 is
select id_fk , name, from table2 where table1.id=table2.id_fk and close_date is null;
then i would loop through and fetch the data related to table1 and table2
fetch c1 into id, n_tab, n_rows;
FETCH c2 INTO id_fk, n_tab2;
I would like some help on how to dynamically access the columns from the tables on table1.
I tried to summarize the best way possible.
If anyone could show me a small example of how i could implement this.
PS: i cant use partitions
Thank you in advance

SQL Cartesian product joining table to itself and inserting into existing table

I am working in phpMyadmin using SQL.
I want to take the primary key (EntryID) from TableA and create a cartesian product (if I am using the term correctly) in TableB (empty table already created) for all entries which share the same value for FieldB in TableA, except where TableA.EntryID equals TableA.EntryID
So, for example, if the values in TableA were:
TableA.EntryID TableA.FieldB
1 23
2 23
3 23
4 25
5 25
6 25
The result in TableB would be:
Primary key EntryID1 EntryID2 FieldD (Default or manually entered)
1 1 2 Default value
2 1 3 Default value
3 2 1 Default value
4 2 3 Default value
5 3 1 Default value
6 3 2 Default value
7 4 5 Default value
8 4 6 Default value
9 5 4 Default value
10 5 6 Default value
11 6 4 Default value
12 6 5 Default value
I am used to working in Access and this is the first query I have attempted in SQL.
I started trying to work out the query and got this far. I know it's not right yet, as I’m still trying to get used to the syntax and pieced this together from various articles I found online. In particular, I wasn’t sure where the INSERT INTO text went (to create what would be an Append Query in Access).
SELECT EntryID
FROM TableA.EntryID
TableA.EntryID
WHERE TableA.FieldB=TableA.FieldB
TableA.EntryID<>TableA.EntryID
INSERT INTO TableB.EntryID1
TableB.EntryID2
After I've got that query right, I need to do a TRIGGER query (I think), so if an entry changes it's value in TableA.FieldB (changing it’s membership of that grouping to another grouping), the cartesian product will be re-run on THAT entry, unless TableB.FieldD = valueA or valueB (manually entered values).
I have been using the Designer Tab. Does there have to be a relationship link between TableA and TableB. If so, would it be two links from the EntryID Primary Key in TableA, one to each EntryID in TableB? I assume this would not work because they are numbered EntryID1 and EntryID2 and the name needs to be the same to set up a relationship?
If you can offer any suggestions, I would be very grateful.
Research:
http://www.fluffycat.com/SQL/Cartesian-Joins/
Cartesian Join example two
Q: You said you can have a Cartesian join by joining a table to itself. Show that!
Select *
From Film_Table T1,
Film_Table T2;
No, you don't want a cartesian product where you join tables without any condition. What you are looking for is a simple self join:
insert into TableB(EntryID1, EntryID2)
select x.EntryID, y.EntryID
from TableA x
join TableA y on x.FieldB = y.FieldB and x.EntryID <> y.EntryID;
EDIT: As you want this table to be up-to-date all the time, consider a view instead of a table (only, then you could not have a manually maintained FieldD).
This should give you the 'cartesian' (its not actually a cartesian, as #ThorstenKettner mentions below - its a self join) you're after, and insert it into TableB:
INSERT INTO TableB (EntryId1, EntryId2, fieldD)
SELECT a.EntryID, b.EntryID, 'Default Value'
FROM TableA a, TableA b
WHERE a.FieldB=b.FieldB
AND a.EntryID<>b.EntryID
You don't need any relationship between the two tables for the Trigger, although I would suggest you have a foreign key relationship setup anyway, so that you never get an entry in TableB.EntryID1 or TableB.EntryID2 that doesn't have a corresponding entry in TableA.EntryID..
For the Triggers, you'd do something like this for the insert (you don't need to check TableB in this case because you know that your new TableA.EntryId doesn't exist there yet:
CREATE TRIGGER ins_tableA AFTER INSERT ON TableA
FOR EACH ROW
BEGIN
INSERT INTO TableB (EntryId1, EntryId2, fieldD)
SELECT a.EntryID, b.EntryID, 'Default Value'
FROM TableA a, TableA b
WHERE a.FieldB=b.FieldB
AND a.EntryID=NEW.EntryID
AND a.EntryID<>b.EntryID;
END;
And for the update, you could delete all the corresponding rows from TableB first, and then re-run the insert. Something like this:
CREATE TRIGGER upd_tableA AFTER UPDATE ON TableA
FOR EACH ROW
BEGIN
DELETE FROM TableB b
WHERE b.EntryId1 = NEW.EntryId
OR b.EntryId2 = NEW.EntryId;
INSERT INTO TableB (EntryId1, EntryId2, fieldD)
SELECT a.EntryID, b.EntryID, 'Default Value'
FROM TableA a, TableA b
WHERE a.FieldB=b.FieldB
AND a.EntryID=NEW.EntryID
AND a.EntryID<>b.EntryID;
END;
None of this is tested I'm afraid, but hopefully it'll put you on the right track..

Read Rows But search first

I want to make an import system that will look into one Datasource and copy new records into another DataSource.
Monthly I want to copy some tables data from one datasource to another datasource
SourceTableName : srcTable
DestinationTableName : destTable
Suppose first month in source table I have:
Id Name 1 john
3 Rahul 5 Andrew
All three rows Will be copy into desTable
Suppose Second Month in Source Table I have
Id Name 1 John
3 Rahul 5 Andrew
6 Vikas 7 Sonam
8 Divya
Firstly Sql Should get the last Row of desTable
and match that row into srcTable
and extract all new records from scrTable and copied into desTable
.....
Please let me know how I can write query for fulfill above purpose. If there is shorter approach, that would be helpful too.
Since you only care about adding new records, and don't need to handle updates or deletes... You can simply add the record from the source table if it doesn't exist in the destination table:
INSERT INTO destTable (ID, Name)
SELECT s.ID, s.Name
FROM
srcTable s
LEFT OUTER JOIN destTable d ON d.ID = s.ID
WHERE
d.ID IS NULL
You can write a stored procedure for do this action and execute that every time you want.
for this action you can from bellow query:
(Part 1 for insert new data, Part 2 for update change data)
Insert Into DestinationTable(ID, Name)
Select ID, Name
From SoiurceTable
Where Not Exists
(Select *
From TDestinationTablest
Where DestinationTable.ID = SoiurceTable.ID)
Go
Update DestinationTable
Set DestinationTable.Name = SoiurceTable.Name
From DestinationTable, SoiurceTable
Where DestinationTable.ID = SoiurceTable.ID
I hope it's helpful.

how to query with child relations to same table and order this correctly

Take this table:
id name sub_id
---------------------------
1 A (null)
2 B (null)
3 A2 1
4 A3 1
The sub_id column is a relation to his own table, to column ID.
subid --- 0:1 --- id
Now I have the problem to make a correctly SELECT query to show that the child rows (which sub_id is not null) directly selected under his parent row. So this must be a correctly order:
1 A (null)
3 A2 1
4 A3 1
2 B (null)
A normal SELECT order the id. But how or which keyword help me to order this correctly?
JOIN isn't possible I think because I want to get all the rows separated. Because the rows will be displayed on a Gridview (ASP.Net) with EntityDataSource but the child rows must be displayed directly under his parent.
Thank you.
Look at Managing Hierarchical Data in MySQL.
Since recursion is an expensive operation because basicly you're firing multiple queries to your database you could consider using the Nested Set Model. In short you're assigning numbers to ranges in your table. It's a long article but it worth reading it. I've used it during my internship as a solution not to have 1000+ queries, But bring it down to 1 query.
Your handling 'overhead' now lies at the point of updating the table by adding, updating or deleting records. Since you then have to update all the records with a bigger 'right-value'. But when you're retrieving the data, it all goes with 1 query :)
select * from table1 order by name, sub_id will in this case return your desired result but only because the parents names and the child name are similar. If you're using SQL 2005 a recursive CTE will work:
WITH recurse (id, Name, childID, Depth)
AS
(
SELECT id, Name, ISNULL(childID, id) as id, 0 AS Depth
FROM table1 where childid is null
UNION ALL
SELECT table1.id, table1.Name, table1.childID, recurse.Depth + 1 AS Depth FROM table1
JOIN recurse ON table1.childid = recurse.id
)
SELECT * FROM recurse order by childid, depth
SELECT
*
FROM
table
ORDER BY
COALESCE(id,sub_id), id
btw, this will work only for one level.. any thing more than that requires recursive/cte function