Microsoft Access - Merging Multiple Tables with Same Fields - ms-access

I am trying to figure out how to create a table that merges records from two tables with identical structure. Each table will have the following fields: a document_ID as the primary key, a documentNumber, a documentRevision, and a documentTitle. The only difference in the two tables is that each table holds a certain "Type" of document. The merged table should end up holding ALL documents from both tables.
I have tried to use an append query, but I ran into an issue where I couldn't figure out how to get the query to run when a record was inserted into each table.
In my search online, I saw some things about "Joining", but I had no luck at understanding how to make it work.
Any help is appreciated!
table1 : Documents of Type 1
+---------------+--------------------+-----------------+-------------------+
| Document ID | Document Number | Document Rev | Document Title |
+---------------+--------------------+-----------------+-------------------+
| 1 | GCD_111 | - | Title GCD1 |
| 2 | GCD_222 | A | Title GCD2 |
| 3 | GCD_333 | B | Title GCD3 |
+---------------+--------------------+-----------------+-------------------+
table2 : Documents of Type 2
+---------------+--------------------+-----------------+-------------------+
| Document ID | Document Number | Document Rev | Document Title |
+---------------+--------------------+-----------------+-------------------+
| 4 | TSR_111 | - | Title TSR1 |
| 5 | TSR_222 | A | Title TSR2 |
| 6 | TSR_333 | B | Title TSR3 |
+---------------+--------------------+-----------------+-------------------+
Result Table: Documents of Type 1 and Type 2
+---------------+--------------------+-----------------+-------------------+
| Document ID | Document Number | Document Rev | Document Title |
+---------------+--------------------+-----------------+-------------------+
| 1 | GCD_111 | - | Title GCD1 |
| 2 | GCD_222 | A | Title GCD2 |
| 3 | GCD_333 | B | Title GCD3 |
| 4 | TSR_111 | - | Title TSR1 |
| 5 | TSR_222 | A | Title TSR2 |
| 6 | TSR_333 | B | Title TSR3 |
+---------------+--------------------+-----------------+-------------------+

You can break the problem down. First, which are the records in table1 and table2 not already in resulttable? When you have a query to do this, append the results to the resulttable.
I'll use a slight modification of your example, where one record is already in resulttable:
resulttable:
+-------------+-----------------+--------------+----------------+
| Document ID | Document Number | Document Rev | Document Title |
+-------------+-----------------+--------------+----------------+
| 1 | GCD_111 | - | Title GCD1 |
+-------------+-----------------+--------------+----------------+
First, the query
INSERT INTO resulttable
SELECT a.[Document ID], a.[Document Number], a.[Document Rev], a.[Document Title]
FROM
(SELECT t1.[document id], t1.[Document Number], t1.[Document Rev], t1.[Document Title]
FROM table1 AS t1
LEFT JOIN resulttable AS rt on t1.[Document ID] = rt.[Document ID]
WHERE rt.[Document ID] IS NULL
UNION ALL
SELECT t1.[document id], t1.[Document Number], t1.[Document Rev], t1.[Document Title]
FROM table2 AS t1
LEFT JOIN resulttable as rt on t1.[Document ID] = rt.[Document ID]
WHERE rt.[Document ID] IS NULL) AS a
Explanation: records in table1 and table2 not already in resulttable?
First, do this for table1. We can do the same for table2 later.
As you mentioned, we can use a JOIN. I used a LEFT JOIN here to work out where the two tables do NOT interect i.e. look at all table1 records and show me which ones are not already in resulttable. If you select all records from table1 and the matching resulttable records (intersecting on [Document ID], you'll get a better idea of how this works:
select t1.*, rt.*
from table1 as t1
left join resulttable as rt on t1.[Document ID] = rt.[Document ID]
Because we want the parts that do NOT match, we want the null bits. So, we can modify the last query by specifying WHERE resulttable records are null and specifying the column names we want. This will make the results look exactly how we want them to look for the ultimate INSERT. That is:
select t1.[Document ID], t1.[Document Number], t1.[Document Rev], t1.[Document Title]
from table1 as t1
left join resulttable as rt on t1.[Document ID] = rt.[Document ID]
WHERE rt.[Document ID] IS NULL
Next, UNION ALL to also get the "new" results from table2. (See the final query for where this UNION ALL is.)
Then I wrapped the SELECT.. UNION ALL SELECT.. in parentheses and gave it the alias "a". This allows me to work with that whole group inside the parentheses as if it was a table called "a".
After that, the rest is just a regular INSERT statement.

Related

INNER JOIN on One Table but different Parameter

I am trying to get different values on rows of one table, and I can't think of how to that.
Lets say for example:
table1
id | name | empCode | insCode
1 John | E101 | I101
table2
id | code | name | role
1 | E101 | Mich | 2
2 | I101 | Bran | 3
table1 has reference id of table2, and empCode and insCode in table1 dependes on code and role in table2.
What I want is like this:
id | code | name | empCode | insCode | role |
1 | ? | John | E101 | I101 | ? |
I honestly don't know if its possible to retrieve multiple rows in same table in one select query.
If its not, what other possible solutions can I go with?
There is problem in your table design but you can get as your expected with below query:
select
result1.id,
result1.code,
result1.name,
result1.empCode,
result1.insCode,
result1.role as role_of_empCode,
result2.role as role_of_insCode
from (
SELECT tbl1.id,
tbl2.code,
tbl1.name,
tbl1.empCode,
tbl1.insCode,
tbl2.role
FROM `table2` tbl2
INNER JOIN `table1` tbl1
on tbl2.code = tbl1.empCode
) as result1,
`table2` result2
where result1.insCode = result2.code
ORDER BY result1.id;
You can check in this link!
Try something like:
SELECT a.*, b.role FROM
table1 a inner join table2 b on a.id=b.id
Also you may want to consider removing empcode and inscode from table 2 since its being redundant in table 1 OR vice versa depending on what your objectives are.

IN by other column

How to put a column in the IN?
Example:
SELECT tb1.*,
(SELECT GROUP_CONCAT(name)
FROM tb2
WHERE id IN( tb1.ids_tb2 )) AS names
FROM tb1
Column tb1.ids_tb2 stores "1,2,3"
This is not working.
++++
I need 'ids_tb2' inside the IN
Example Tables http://sqlfiddle.com/#!9/08cfa9/1
Ids_tb2 = 1,3,4
Names != Fruit1,Fruit3,Fruit4
tks
Your table structure is not really ideal for this task. In database design you should always preserve the 'atomicity' of data, i. e. you should never work with lists of ids in any column. Instead use a link table lnk like this
| gid | fid |
|-----|-----|
| 1 | 1 |
| 1 | 3 |
| 1 | 4 |
| 2 | 1 |
| 2 | 5 |
Having such a structure you can then very easily do
SELECT grp , GROUP_CONCAT(name) fruits
FROM tb1
INNER JOIN lnk ON gid=grid
INNER JOIN tb2 ON frid=fid
GROUP BY grp
see here (demo).
The result will be
| grp | fruits |
|------|----------------------|
| Blue | Fruit1,Fruit3,Fruit4 |
| Red | Fruit1,Fruit5 |
Having said that - you could also do the following with your original database design (see here):
SELECT tb1.id,`group`,GROUP_CONCAT(name) fruits
FROM tb1
INNER JOIN tb2 ON FIND_IN_SET(tb2.id,ids_tb2)>0
GROUP BY `group`
Although I would not recommend doing this. Also you should not be using reserved SQL names for your columns like group, as you will always have to use back-ticks to mask them.
Revisiting ...
Actually, your initial approach does also work, you just have to replace your IN (..) clause by a FIND_IN_SET(..) function call like
SELECT tb1.*,
(SELECT GROUP_CONCAT(name) FROM tb2
WHERE FIND_IN_SET(tb2.id, tb1.ids_tb2)>0) names
FROM tb1
You can do a simple select in the in. Just like this:
SELECT tb1.*,
(SELECT GROUP_CONCAT(name)
FROM tb2
WHERE id IN(select * from tb1.ids_tb2 )) AS names
FROM tb1

Updating values in one table based on another

I have following UPDATE query, but something is wrong when executing.
I'm trying to update values in table1 with values in table import_data, but I need the id from table ids... So the table ids links table1 and *import Simple, isn't it?
UPDATE table1
INNER JOIN import_data ON (
import_data.id = (
SELECT customer_id
FROM ids
INNER JOIN table1 ON (
table1.id = ids.link
)
WHERE ids.type = 'NORMAL'
)
)
SET table1.name = import_data.name;
table1
| id | name |
|----------|-----------|
| AA-00001 | Company 1 |
| AA-00002 | Company 2 |
| AA-00003 | Company 3 |
import_data
| id | name |
|--------|-------------------|
| 401000 | Updated company 1 |
| 401001 | Updated company 2 |
| 401002 | Company 3 |
ids
| link | id | type |
|----------|--------|--------|
| AA-00001 | 401000 | NORMAL |
| AA-00002 | 401001 | NORMAL |
| AA-00003 | 401002 | NORMAL |
Try:
update table1 t1
inner join (
select idata.name, ids.link
from import_data idata
join ids on ids.id = idata.id
where ids.type = 'NORMAL'
) x
on x.link = t1.id
set t1.name = x.name
Demo sqlfiddle
I think it's depends on database you're using. The relevant post is answered here - How can I do an UPDATE statement with JOIN in SQL?
I dont have mysql to check it, but it should work the way you want. Please check.
UPDATE table1
INNER JOIN ids
ON table1.id= ids.link
INNER JOIN import_data
on import_data.id = ids.id
SET table1.name = import_data.name
WHERE ids.type = 'NORMAL';

MySQL: export multiple tables to CSV file

I'm trying to export multiple MySQL tables into a single CSV file, these tables have different number of columns and have nothing in common. An example is below:
table1:
ID| Name
1 | Ted
2 | Marry
null| null
table2:
Married| Age | Phone
Y | 35 | No
N | 25 | Yes
Y | 45 | No
The result that I want to get is:
ID| Name | Married | Age | Phone
1 | Ted | Y | 35 | No
2 | Marry | N | 25 | Yes
null| null | Y | 45 | No
Is it possible to do using MySQL commands? I have tried all types of join but it doesn't give me the result that I need.
Try this query:
SELECT * FROM
(SELECT #n1:=#n1+1 as 'index', Table1.* FROM Table1, (select #n1:=0)t)t1
natural join (SELECT #n2:=#n2+1 as 'index', Table2.* FROM Table2, (select #n2:=0)t1)t2 ;
You can see in this fiddle a working example.
In the example we generate an index column for Table1 and Table2 and natural join the 2 tables.
This way the join is done using the row position as returned by the SELECT of tables without any ORDER operator and usually this is not a good idea!
I'm not quite sure you understand what you are asking but sure you can join two tables without really caring on which rows will be matched:
SET #i1=0;
SET #i2=0;
SELECT * INTO OUTFILE 'xyz' FIELDS TERMINATED BY ','
FROM (SELECT #i1:=#i1+1 as i1, table1.* FROM table1) AS a
JOIN (SELECT #i2:=#i2+1 as i2, table2.* FROM table2) b ON (a.i1=b.i2);

select query having like and case statement in sql server 2008

I have a table
--------------------
ID | Name | RollNO
--------------------
1 | A | 18
--------------------
2 | B | 19RMK2
--------------------
3 | C | 20
--------------------
My second table is
-----------------------
OldRollNo | NewRollNo
-----------------------
18 | 18RMK1
-----------------------
19 | 19RMK2
-----------------------
20 | 20RMK3
-----------------------
21 | 21RMK4
-----------------------
22 | 22RMK5
-----------------------
I want the resulting table like
----------------------------------
ID | Name | RollNo | LatestRollNo
----------------------------------
1 | A | 18 | 18RMK1
----------------------------------
2 | B | 19RMK2 | 19RMK2
----------------------------------
3 | C | 20 | 20RMK3
----------------------------------
What would be the select query like? This is just the replica of my problem. I have used CASE Statement with the select query but as the records in my table is large, it's taking too much time. In my second table the OldRollNo Column is unique.One more thing is that in the resultant RollNo column if the newly assigned RollNo is already present then it should be copied exactly to the next column i.e LatestRollNo. I have to check only those RollNo which are old.
Thanks.
Try something like this:
select t1.ID
, t1.Name
, t1.RollNO
, LatestRollNO = coalesce(n.NewRollNo, o.NewRollNo)
from t1
left join t2 o on t1.RollNO = o.OldRollNo
left join t2 n on t1.RollNO = n.NewRollNo
SQL Fiddle with demo.
It sounds like your issue is performance not logic; something like this should hopefully allow approriate index usage assuming you have the appropriate indexes on t2.OldRollNo and t2.NewRollNo.
The problem with OR or CASE in a WHERE clause is that these don't always lend themselves to efficient queries; hopefully this will be a bit more useful in your case.
select f.ID, f.name, f.RollNo, s.NewRollNo as "Latest RollNo"
from FirstTable f
inner join
SecondTable s on f.RollNo = s.OldRollNo or f.RollNo = s.NewRollNo
select t.id,t.name,t.rollno,tt.newrollno as latestrollno from
talble1 t
left join
table2 tt on t.rollno = tt.oldrollno
You need to use inner join.
SELECT t1.ID,t1.Name,t2.RollNo,t2.NewRollNo AS LatestRollNo
FROM Table1 t1
INNER JOIN Table2 t2
ON t1.RollNo=t2.OldRollNo OR t1.RollNo=t2.NewRollNo