Insert into a table using multiple tables [duplicate] - sql

This question already has answers here:
SQL JOIN and different types of JOINs
(6 answers)
Closed 4 years ago.
I am new to using SQL Server. I have an assignment, and the lecturer is not showing us how to use the tools he wants the assignment to be completed with.
I am trying to come up with a query that will insert the primary key of 3 dimension tables into as well as trying to insert data from the source data in another table.
The source data is a data set of 10000+ Apps on the Google Play Store.
See below for my table and what I need
DimContentRating - there are 6 content ratings
ContentRatingID(PK) Content Rating
--------------- --------------
1 Everyone
2 Teen
DimCategory - there are 34 categories
CategoryID(PK) Category
---------- --------
1 Education
2 Finance
DimInstalls - there are many ranges of installs
InstallID(PK) Installs
---------- --------
1 10000+
2 100000+
googleplaystore - the table with the 10000+ records and original data
App Category Rating Reviews Installs Price Content_Rating
--- -------- ------ ------ -------- ----- --------------
GMAT
Question Education 4.2 240 10000+ Free Everyone
Bank
Ace Elite Finance 4.1 2898 100000+ Free Everyone
How I need it to look
AppFact - The table that needs the tables above to be broken down from the above tables and inserted using links from Foreign Keys
AppFactID Category Rating Reviews Installs Price Content_Rating
--------- -------- ------ ------ -------- ----- --------------
1 1 4.2 240 1 Free 1
2 2 4.1 2898 2 Free 1
I do apologize for not having a query that I tried writing to get it to work but I have not been shown much at all about SQL Server and so the best I know is general queries. What I do know is I need to use the below as well as possible inner joins?
INSERT INTO AppFact(...)
SELECT ...
FROM ...
Am I on the right track?

Assuming you already create the table AppFact with PK AppFactID, the query you're looking for is:
INSERT INTO AppFact (Category, Rating, Reviews, Installs, Price, Content_Rating)
SELECT c.CategoryID, a.Rating, a.Reviews, i.Installs, a.Price, r.ContentRatingID
FROM googleplaystore a
INNER JOIN DimContentRating r ON a.Content_Rating = r.Content_Rating
INNER JOIN DimCategory c ON a.Category = c.Category
INNER JOIN DimInstalls i ON a.Installs = i.Installs
You should take a look to JOINs in SQL Server

Related

Fetch results of joined tables as columns in postgres

I trying to figure out a way to generate a SQL query, to be used in a view, to generate an Excel like format for parent-child relationship.
I have the following tables
Person
id
name
email
accepted
1
A
--
--
2
B
--
--
3
C
--
--
Guest
id
name
accepted
id_person (foreign_key -> person.id)
1
AGuest1
---
1
2
BGuest1
---
2
3
BGuest2
---
2
4
CGuest1
---
3
5
CGuest2
---
3
6
CGuest3
---
3
A person can have multiple guests accompanying him/her.
What I want to do is generate a SQL that gives me the following result:
Person Name
Guest 1 Name
Guest 2 Name
Guest 3 Name
A
AGuest1
--
--
B
BGuest1
BGuest2
--
C
CGuest1
CGuest2
CGuest3
I can generate two separate queries that will generate a list of rows with that information but I am struggling to generate multiple columns based on the information that I have.
I have looked into crosstab() for postgres, but so far I have no luck with generating anything that would like this.
Any help or pointers in the right direction would be helpful, thank you!
You can use CROSSTAB:
SELECT *
FROM CROSSTAB (
'SELECT p.name, g.name, g.name
FROM person p JOIN guest g
ON p.id = g.id_person
ORDER BY 1,2')
AS ("Person Name" varchar(100), "Guest 1 Name" varchar(100),
"Guest 2 Name" varchar(100), "Guest 3 Name" varchar(100));
Please note: This will work for 1 to 3 guest like you described. In case more guests per person are possible, you need to extend this.
I created a working example here: db<>fiddle

Oracle alter table to allow a team to support several charities if they wish change the database to satisfy this requirement

Hi i need help with the following question:
Following requests from several teams, Run Monash would like to allow a team to support
several charities if they wish. Where a team does support several charities they must nominate,
one charity as their prime charity, the one they will provide the main support to.
Change the database to satisfy this requirement.
After making this change add the 'Salvation Army' as the second charity to team number 1.
The team table currently looks like this:
TEAMNO TEAMNAME CARNDATE TEAMNOMEMBER CHARNAME ENTRYID
---------- ------------------------------ --------- ------------ ------------------------------ ----------
1 Gentle Earth 04/APR/18 2 Amnesty International 5
2 Happy Feet 04/APR/18 2 Beyond Blue 14
3 Avengers 06/MAY/19 2 Salvation Army 37
4 Footloose 06/MAY/19 3 Salvation Army 38
5 Happy Feet 06/MAY/19 4 Amnesty International 30
This is what i attempted
alter table team add (
seccharname VARCHAR2(30),
primechar VARCHAR2(30),
);
UPDATE team
INSERT into team (teamno,seccharname,primechar) VALUES ( values (1,'salvation army','Amnesty International');
Not sure what to do to satisfy the question asked.
Your alter statement needs little bit correction. You already have CHARNAME column so you can only rename that to primechar.
ALTER TABLE team RENAME CHARNAME TO primechar;
Then Just correct your update statement -
UPDATE team
SET seccharname = 'salvation army',
primechar = 'Amnesty International'
WHERE TEAMNO = 1;
I think a MERGE statement would suit best for your case :
MERGE INTO team t
USING ( SELECT 1 as teamno,
'salvation army' as seccharname,
'Amnesty International' as primechar
FROM dual
) t2
ON (t2.teamno=t.teamno)
WHEN MATCHED THEN
UPDATE SET seccharname=t2.seccharname, primechar=t2.primechar
WHEN NOT MATCHED THEN
INSERT (teamno, seccharname, primechar)
VALUES ( t2.teamno, t2.seccharname, t2.primechar )
if key column(teamno) matches the newly added null columns will be populated, otherwise they're inserted with null values for the rest of the columns(teamname,carndate,teamnomember).

Merge two versions of database tables with conflicting keys

I have been asked to merge 2 Access databases. They are conflicting versions of the same file.
A database was emailed to somebody. (I know.) Somebody added records to the 'main' copy while somebody else added records to their copy. I want to add the new records from the 'unauthorised' copy into the main version, before utterly destroying all other copies.
Unfortunately, the database has several related tables. As would naturally happen when records are added, records in different versions have conflicting primary keys. These conflicting keys are also used as foreign keys in the new records. A foreign key reference to ID x means different things in the 2 versions.
Is there any hope? I thought of maybe importing it all into excel and using formulas to update the primary and foreign keys.
Is there any way to fix this programatically?
EDIT: Here is a picture showing the full relationships. Tables teachers, tests, and test_results have been changed; the others are the same in both.
In the main database, add a Long field named [oldID] to each table into which you need to append data. Then create Linked Tables pointing to the relevant tables in the "other" database. Since the table names are the same, the linked tables will have a '1' appended to them.
For this example, we have
[teachers]
ID teacher oldID
-- -------- -----
1 TeacherA
2 TeacherB
3 TeacherX
[teachers1]
ID teacher
-- --------
1 TeacherA
2 TeacherB
3 TeacherY
[tests]
ID test_name teacher oldID
-- -------------- ------- -----
1 TeacherA_Test1 1
2 TeacherA_Test2 1
3 TeacherB_Test1 2
4 TeacherX_Test1 3
[tests1]
ID test_name teacher
-- -------------- -------
1 TeacherA_Test1 1
2 TeacherA_Test2 1
3 TeacherB_Test1 2
4 TeacherY_Test1 3
5 TeacherY_Test2 3
Make a note of where the tables diverge. In this case the [teachers] tables diverge after ID=2. So, insert the new rows from [teachers1] into [teachers], putting [teachers1].[ID] into [teachers].[oldID] so we can map old IDs to new ones:
INSERT INTO [teachers] ([teacher], [oldID])
SELECT [teacher], [ID] FROM [teachers1] WHERE [ID]>2
So now we have
[teachers]
ID teacher oldID
-- -------- -----
1 TeacherA
2 TeacherB
3 TeacherX
4 TeacherY 3
Now when we append the new rows from [tests1] into [tests] we can use an INNER JOIN on [teachers].[oldID] to adjust the foreign key values that get inserted:
INSERT INTO [tests] ([test_name], [teacher], [oldID])
SELECT [tests1].[test_name], [teachers].[ID], [tests1].[ID]
FROM [tests1] INNER JOIN [teachers] ON [tests1].[teacher]=[teachers].[oldID]
giving us
[tests]
ID test_name teacher oldID
-- -------------- ------- -----
1 TeacherA_Test1 1
2 TeacherA_Test2 1
3 TeacherB_Test1 2
4 TeacherX_Test1 3
5 TeacherY_Test1 4 4
6 TeacherY_Test2 4 5
Notice how the [teacher] foreign key has been mapped from the value 3 in [tests1] to 4 in [tests], reflecting the new [teachers].[ID] value for 'TeacherY'.
You can then repeat the process for child tables of [tests].
(Once the cleanup is complete you can remove the table links and drop the [oldID] columns.)
Is there any way to fix this programatically?
No. This must be done by a human capable of reading and understanding the data and taking decisions.
Create a query with an inner join between table one and table two, another query with an outer join between table one and table two, and another query with an outer join between table two and table one.
Now you can study the differences and decide which version of similar records to be kept and which records are completely new and should be kept - some with a new Primary Key.

Are Append Queries in a self joining table possible

I have tblEmployee that contains 3 fields:
ID: AutoNumber
Name: Text
Supervisor: Number [as a lookup in tblEmployee]
I wish to append new data to this table from tblNewEmployees that has the exact same structure as the previous table.
Can this be done if I have the ID field as an autonumber?
I have tried various queries (for example first appending only the Name field as step 1, and then trying with a second update query to get the supervisor) but all produced garbage, hence my question whether this is possible using AutoNumbers in the first place.
I suppose it can be done in your structure (adjacency list model) in an iterative way i.e. add the employee(s) at the top of the tree, query the database to get their auto-generated id(s), then add the employees in the next level down using the previously queried id(s), then repeat for each level down.
While possible, is it desirable? Presumably every employee already has a unique id e.g. payroll number, social security number, etc. If unsure, ask the payroll person.
Removing the dependency of the database in generating employee ids will probably free you from the aforementioned iterative process. It is preferable for inserts to be deterministic, predictable, scritpable as a one-off, etc.
Another thing to consider is that your may be modelling a tree structure when you may want a hierarchy. The examples Celko used to give: the army is a hierarchy because if you shoot your sergeant you still have to take orders from your captain; on the other hand, a river system is tree because if your dam one tributary then all downstream tributaries run dry.
It seems to me with your design, when a supervisor leaves (is deleted from the table) then you are left with an unsupervised employee (missing data, therefore data integrity is corrupted), whereas you'd want the next senior employee to take their place (hierarchy). An update in your structure could be a lot if work i.e. iterative again.
While the adjacency list model may be intuitive, it is not always the easiest to work with in SQL DML. Consider other models e.g. nested sets. That said, with Access, SQL DML is almost always painful because it doesn't support procedural SQL code in stored procs, triggers, etc; even a simple update can fail due to 'non-updatable query' (view) restrictions. So as usual, I must advise you to consider a more capable DBMS if at all possible.
Yes, it is possible to merge the two tables when the destination table has an AutoNumber ID. There are two possible scenarios:
Scenario 1: No overlap of ID values between the two tables
[tblEmployee]
ID Name Supervisor
-- ---------- ----------
1 Director A
2 Manager A 1
3 Worker A 2
[tblNewEmployees]
ID Name Supervisor
--- ---------- ----------
101 Director B
102 Manager B 101
103 Worker B 102
Since the Access Database Engine allows us to insert arbitrary values into an AutoNumber column, this case is trivial. Just ...
INSERT INTO tblEmployee (ID, [Name], Supervisor)
SELECT ID, [Name], Supervisor FROM tblNewEmployees
... and we're done:
[tblEmployee]
ID Name Supervisor
--- ---------- ----------
1 Director A
2 Manager A 1
3 Worker A 2
101 Director B
102 Manager B 101
103 Worker B 102
Scenario 2: Common ID values between the two tables
[tblEmployee]
ID Name Supervisor
-- ---------- ----------
1 Director A
2 Manager A 1
3 Worker A 2
[tblNewEmployees]
ID Name Supervisor
-- ---------- ----------
2 Director B
5 Manager B 2
7 Worker B 5
In this case we need to map the old ID values to the new ID values when the new rows are inserted. To do that, add a new column to [tblEmployee]
ALTER TABLE tblEmployee ADD oldID LONG
then insert the new rows, putting tblNewEmployees.ID into tblEmployee.oldID
INSERT INTO tblEmployee (oldID, [Name])
SELECT ID, [Name] FROM tblNewEmployees
giving us
[tblEmployee]
ID Name Supervisor oldID
-- ---------- ---------- -----
1 Director A
2 Manager A 1
3 Worker A 2
4 Director B 2
5 Manager B 5
6 Worker B 7
Then we can update the Supervisor column with the new ID values
UPDATE
(
tblEmployee emp
INNER JOIN
tblNewEmployees new
ON emp.oldID = new.ID
)
INNER JOIN
tblEmployee emp2
ON new.Supervisor = emp2.oldID
SET emp.Supervisor = emp2.ID
producing
[tblEmployee]
ID Name Supervisor oldID
-- ---------- ---------- -----
1 Director A
2 Manager A 1
3 Worker A 2
4 Director B 2
5 Manager B 4 5
6 Worker B 5 7
We can then drop the [oldID] column if desired.

SQL query to return data from two separate rows in a table joined to a master table

I have a TWO tables of data with following fields
table1=(ITTAG,ITCODE,ITDESC,SUPcode)
table2=(ACCODE,ACNAME,ROUTE,SALMAN)
This is my customer master table that contains my customer data such as customer code, customer name and so on...
Every Route has a supervisor (table1=supcode) and I need to know the supervisor name in my table which both supervisor name and code exist in one table.
table1 has contain all names separated by ITTAG. For example, supervisor's name has ITTAG='K'; also salesman's name has ITTAG='S'.
ITTAG ITCODE ITDESC SUPCODE
------ ------ ------ -------
S JT JOHN TOMAS TF
K WK VIKI KOO NULL
Now this is the result which I want
ACCODE ACNAME ROUTE SALEMANNAME SUPERVISORNAME
------- ------ ------ ------------ ---------------
IMC1010 ABC HOTEL 01 JOHN TOMAS VIKI KOO
I hope this this information is sufficient to get the query..
Your data structure is either not clear or incomplete. It would help if you showed the actual example data for Table1 too, but there would be trouble.
SELECT t2.ACCODE, t2.ACNAME, t2.ROUTE, a1.ITDESC AS Salesman, a2.ITDESC AS Supervisor
FROM table1 AS t1
JOIN table2 AS a1 ON t1.SALMAN = a1.ITCODE
JOIN table2 AS a2 ON t1.?????? = a2.SUPCODE
It is not clear whether I've managed the join between Table1 and Table2 for the salesman information correctly; it is plausible, but the join for the supervisor should be similar, and yet there isn't a way to make that work. Hence the '??????' in the query.
The basic technique for joining twice to a single table is to cite it twice with different aliases, as shown. I usually use one letter or a letter and a digit for the aliases, as shown.