Dears, I have an SQL problem. I need to join 2 databases, with 2 tables each. I have the pictures of the tables of the databases here. Thank you very much for your helps.
-
Please post what you have tried so far, post the code and the problem you are having. – Spoody May 20 '18 at 22:14
1 Answers
With a UNION ALL you can get 1 combined resultset from 2 selects.
Then you can group that and SUM the amounts per date.
So you're probably looking for something like this:
select
q.ID,
q.Name,
nullif(sum(case when q.Date = '2018-05-01' then q.Amount end), 0) as "5/1/2018",
nullif(sum(case when q.Date = '2018-05-02' then q.Amount end), 0) as "5/2/2018"
from
(
select u1.ID, u1.Name, a1.Date, a1.Amount
from DB1.Table1 AS u1
join DB1.Table2 AS a1 on (a1.ID = u1.ID and a1.Amount is not null)
where a1.Date IN ('2018-05-01', '2018-05-02')
union all -- combines the results of the 2 selects into one resultset
select u2.ID, u2.Name, a2.Date, a2.Amount
from DB2.Table1 AS u2
join DB2.Table2 AS a2 on (a2.ID = u2.ID and a2.Amount is not null)
where a2.Date IN ('2018-05-01', '2018-05-02')
) AS q
group by q.ID, q.Name
order by q.ID;
An alternative is to JOIN them all up.
select
coalesce(a1.ID, a2.ID) as ID,
max(coalesce(u1.Name, u2.Name)) as Name,
max(case
when coalesce(a1.Date, a2.Date) = '2018-05-01'
and coalesce(a1.Amount, a2.Amount) is not null
then coalesce(a1.Amount, 0) + coalesce(a2.Amount, 0)
end) as "5/1/2018",
max(case
when coalesce(a1.Date, a2.Date) = '2018-05-02'
and coalesce(a1.Amount, a2.Amount) is not null
then coalesce(a1.Amount, 0) + coalesce(a2.Amount, 0)
end) as "5/2/2018"
from DB1.Table2 AS a1
full join DB2.Table2 AS a2 on (a2.ID = a1.ID and a2.Date = a1.Date)
left join DB1.Table1 AS u1 on (u1.ID = a1.ID)
left join DB2.Table1 AS u2 on (u2.ID = a2.ID)
where coalesce(a1.Date, a2.Date) IN ('2018-05-01', '2018-05-02')
group by coalesce(a1.ID, a2.ID)
order by coalesce(a1.ID, a2.ID);
But then note that this way, that there's an assumption that the two Table2 have a uniqueness on (ID, Date)
T-Sql test data: declare @DB1_Table1 table (id int, Name varchar(30)); declare @DB2_Table1 table (id int, Name varchar(30)); declare @DB1_Table2 table (id int, [Date] date, Amount decimal(8,2)); declare @DB2_Table2 table (id int, [Date] date, Amount decimal(8,2)); insert into @DB1_Table1 (id, Name) values (1,'Susan'),(2,'Juan'),(3,'Tracy'),(4,'Jenny'),(5,'Bill'); insert into @DB2_Table1 (id, Name) values (1,'Susan'),(2,'Juan'),(3,'Tracy'),(4,'Jenny'),(5,'Bill'); insert into @DB1_Table2 (id, [Date], Amount) values (1,'2018-05-01',20),(2,'2018-05-01',null),(3,'2018-05-01',30),(4,'2018-05-01',50),(5,'2018-05-01',null), (1,'2018-05-02',15),(2,'2018-05-02',40),(3,'2018-05-02',25),(4,'2018-05-02',8),(5,'2018-05-02',null); insert into @DB2_Table2 (id, [Date], Amount) values (1,'2018-05-01',null),(2,'2018-05-01',15),(3,'2018-05-01',20),(4,'2018-05-01',10),(5,'2018-05-01',null), (1,'2018-05-02',15),(2,'2018-05-02',30),(3,'2018-05-02',35),(4,'2018-05-02',null),(5,'2018-05-02',30);

- 28,916
- 5
- 31
- 45
-
Thank LukStorms. Since I am using MS Access, I had changed the "case" to "switch" and the SQL statement became as below: – Tony Nguyen May 22 '18 at 02:17
-
Sorry, I don't know how to indent, and line break as you did in your answer. After starting the SQL statement querry: It asks me for the dates values, the a2.amount, ID, and Name. Then return with nothing. – Tony Nguyen May 22 '18 at 02:46
-
SELECT ID, Name,
Sum(Switch(Date=#5/1/2018#,a1.Amount+a2.Amount)) AS ["5/1/2018"], Sum(Switch(Date=#5/2/2018#,a1.Amount+a2.Amount)) AS ["5/2/2018"] FROM (select u1.EmpID, u1.FirstName, a1.Date, a1.Amount from Employee u1 INNER join Sale a1 on (a1.EmployeeID = u1.EmpID and a1.Amount is not null) union select u2.EmpID, u2.FirstName, a2.Date, a2.Amount from Employee1 u2 INNER join Sale1 a2 on (a2.EmployeeID = u2.EmpID and a2.Amount is not null) ) AS q GROUP BY ID, Name ORDER BY ID; – Tony Nguyen May 22 '18 at 02:52 -
@TonyNguyen Didn't know this was for MS Access. But realise that the outer query only knows q.Amount. Also note that in other databases, a UNION removes duplicates, while a UNION ALL keeps the duplicates. That affects a SUM. – LukStorms May 22 '18 at 08:09
-
About [UNION vs UNION ALL](https://stackoverflow.com/questions/49925/what-is-the-difference-between-union-and-union-all) – LukStorms May 22 '18 at 08:47
-
Thank you very much LukStorms for your helps and your promptly responses. After I changed the words in the query, it is working now except there is a problem. The employee that did not make any "amount" is still list in the query. – Tony Nguyen May 24 '18 at 01:05
-
Now I want to post a picture of the problem that I mention above on here but I don't know how. Could you tell me how? Thank you. – Tony Nguyen May 24 '18 at 01:15
-
@TonyNguyen If it's about putting a picture in your question? If you see the page on your pc desktop, then there should be button in the edit window for that. Or on your tablet/smartphone if you see the page in desktop view. But I think that StackOverflow blocks showing pictures for the low-reputation-point users. So they won't post a picture of code while they should include the code as text .But adding a link should be possible. I never seen people posting pictures in comments, so not sure that's even possible. – LukStorms May 24 '18 at 07:45
-
@TonyNguyen You say that the one without amount is still in the result. Is that Amount field a number field that containst NULL's? Or is it a text field that can contain empty strings? The SQL avoids the NULL amounts after all. Well, in the picture of the question there's one empty amount in the result. Which is normal, since there's an amount for the other date. The SUM for the empty amount would be 0 then. If you don't want to show 0, then switch a 0 to NULL? – LukStorms May 24 '18 at 07:57
-
Thank you very much, LukStorms. I have the picture of my new question for you but I could not post it up as what I did for the first time I asked you. So now we will try to use my first picture again for my new question. – Tony Nguyen May 25 '18 at 08:05
-
-
My new question is: as if the last line of the "DB1 - Table 2" the "ID = 5" did not make that "30" then at the "After Queried - Result Table" the person named "Bill" with "ID = 5" should not be listed in that table. However, your query will show all the persons in my "DB1 - Table 1" and "DB1 - Table 2" even they did not make any amount in those 2 days. Please assume that my real tables have more than 10 persons each. – Tony Nguyen May 25 '18 at 08:14
-
To make it clear, my those 2 tables of "DB1 - Table 1" and "DB1 - Table 2" have 5 persons, but if we assume that the amount of "30" is not in that "DB1-Table 2" then only 4 persons make "Amount" of either "5/1/2018" or "5/2/2018" or on both dates. Bill "5" did not make any "Amount" in both dates so there are no record in the 2 tables of "DB1 - Table 1" and "DB1 - Table 2", however his ID and Name still listed in my results. I would like to have his ID and Name are not listed. Thank you for your help. – Tony Nguyen May 25 '18 at 08:23
-
@TonyNguyen are you aware that after a GROUP BY that you can use a [HAVING](https://www.w3schools.com/sql/sql_having.asp) with criteria for the aggregated fields. Just use that to filter out the empties. – LukStorms May 25 '18 at 09:31
-
@TonyNguyen Another thing. If the table has other dates, then you can optimize the SQL by adding WHERE clauses to the inner selects so it only selects for the dates you're counting on. That way on my first solution those with 2 empties on 1 of the 2 dates won't be in the combined result of the union all. As in f.e.`WHERE a1.Date IN (....)` ....`WHERE a2.Date IN (....)` – LukStorms May 25 '18 at 10:17
-
Thank you very much, LukStorm. I could not do these by myself without your big help. Thanks and a lot of thanks. I will post my query next below here. Please suggest if I have another way to make the query shorter because I will have to use the range of 2 weeks (14 days) instead of 1 week (7 days) right now in the query. So with this current query I have to have 14 sums in the SELECT. Also, could I aggregate for the "count" of how many time each person (or ID) make no NULL "Amount"? – Tony Nguyen May 25 '18 at 17:21
-
SELECT distinct EmpID, FirstName, Sum(Switch(q.DateS=#4/26/2018#, q.Amount)) AS [4/26/2018], Sum(Switch(q.DateS=#4/27/2018#, q.Amount)) AS [4/27/2018], Sum(Switch(q.DateS=#4/28/2018#, q.Amount)) AS [4/28/2018], Sum(Switch(q.DateS=#4/29/2018#, q.Amount)) AS [4/29/2018], Sum(Switch(q.DateS=#4/30/2018#, q.Amount)) AS [4/30/2018], Sum(Switch(q.DateS=#5/1/2018#, q.Amount)) AS [5/1/2018], Sum(Switch(q.DateS=#5/2/2018#, q.Amount)) AS [5/2/2018] FROM – Tony Nguyen May 25 '18 at 17:25
-
FROM ( SELECT u1.EmpID, u1.FirstName, a1.DateS, a1.Amount FROM Employee AS u1 INNER JOIN Sale AS a1 on (a1.EmployeeID = u1.EmpID AND a1.Amount IS NOT NULL) WHERE a1.DateS BETWEEN #4/26/2018# AND #5/2/2018# UNION ALL SELECT u2.EmpID, u2.FirstName, a2.DateS, a2.Amount FROM Employee1 AS u2 INNER JOIN Sale1 a2 on (a2.EmployeeID = u2.EmpID AND a2.Amount IS NOT NULL) WHERE a2.DateS BETWEEN #4/26/2018# AND #5/2/2018# ) AS q GROUP BY EmpID, FirstName ORDER BY EmpID; – Tony Nguyen May 25 '18 at 17:26
-
@TonyNguyen To be honest, it's been too long for me that I dabbled with ms access. But I noticed that it also has a way to PIVOT, via a crosstab. F.e. in [this SO question](https://stackoverflow.com/questions/48027329/). I think it has even a wizard for it. But when I wrote this answer I limited myself to standard old SQL that would run on most RDBMS. So I suggest that you create a new question about how to transform your query into an ms access pivot. Don't forget to add the ms access tags. – LukStorms May 25 '18 at 19:13
-
Btw, when including test data and expected results then the SO community prefers to see it added as text. Since it's easier to copy&paste text than typing it yourself based on a screenshot. – LukStorms May 25 '18 at 19:21
-
Thank you very much LukStorm. I will post the query, and pictures of the tables to the new question as you suggested. Again, I am really appreciated for your helps. – Tony Nguyen May 27 '18 at 06:53