0

I have two tables with relationship defined in query, my objective is to combine the two tables without duplicating the inventory and variance information.

The inventory information in table 1 should not duplicate since it is already the summary inventory, while in table two, I need to display it by item since I want to view technician location information.

Also if item from table 1 doesn’t have record in table 2 (vice versa) still I need to display it details. my current workaround for this scenario is to create two queries then export the output in excel then apply some vlookups.

Table 1 Details:

+---------+-----------+----------+-----------+
| ITEMID  | WAREHOUSE | LOCATION | INVENTORY |
+---------+-----------+----------+-----------+
| ITEM001 | WHS001    | LOC001   | 5         |
| ITEM002 | WHS001    | LOC002   | 4         |
| ITEM003 | WHS001    | LOC003   | 2         |
+---------+-----------+----------+-----------+

Table 2 details:

+---------+-----------+----------+--------------+-----------+
| ITEMID  | WAREHOUSE | LOCATION | LOCATIONNAME | INVENTORY |
+---------+-----------+----------+--------------+-----------+
| ITEM001 | WHS001    | T01      | TECH001      | 1         |
| ITEM001 | WHS001    | T02      | TECH002      | 2         |
| ITEM001 | WHS001    | T03      | TECH003      | 3         |
| ITEM002 | WHS001    | T01      | TECH001      | 1         |
| ITEM002 | WHS001    | T02      | TECH002      | 3         |
+---------+-----------+----------+--------------+-----------+

Revised Query:

SELECT
  a.ITEMID, a.WAREHOUSE, a.LOCATION, a.INVENTORY,
  b.ITEMID, b.WAREHOUSE, b.LOCATION, b.LOCATIONNAME, b.INVENTORY,
  (a.INVENTORY-b.INVENTORY) as VARIANCE
FROM Table1  as a
INNER JOIN Table2 as b ON a.ITEMID = b.ITEMID
GROUP by
  a.ITEMID, a.WAREHOUSE, a.LOCATION,
  b.ITEMID, b.WAREHOUSE, b.LOCATION, b.LOCATIONNAME, a.inventory, b.inventory
order by a.ITEMID ASC

UNION ALL

SELECT
  NULL, NULL, NULL, null, 
  t.ITEMID, t.WAREHOUSE, t.LOCATION, t.LOCATIONNAME, t.inventory, NULL
from table2 t
where t.ITEMID > (select MIN (t.itemid) from table2 where  itemid = t.itemid );

Output:

+----------+-------------+------------+-------------+----------+-------------+------------+--------------+-------------+----------+
| a.ITEMID | a.WAREHOUSE | a.LOCATION | a.INVENTORY | b.ITEMID | b.WAREHOUSE | b.LOCATION | LOCATIONNAME | b.INVENTORY | VARIANCE |
+----------+-------------+------------+-------------+----------+-------------+------------+--------------+-------------+----------+
| ITEM001  | WHS001      | LOC001     | 5           | ITEM001  | KITBAG      | T01        | TECH001      | 1           | 4        |
| ITEM001  | WHS001      | LOC001     | 5           | ITEM001  | KITBAG      | T02        | TECH002      | 2           | 3        |
| ITEM001  | WHS001      | LOC001     | 5           | ITEM001  | KITBAG      | T03        | TECH003      | 3           | 2        |
| ITEM002  | WHS001      | LOC002     | 4           | ITEM002  | KITBAG      | T01        | TECH001      | 1           | 3        |
| ITEM002  | WHS001      | LOC002     | 4           | ITEM002  | KITBAG      | T02        | TECH002      | 3           | 1        |
+----------+-------------+------------+-------------+----------+-------------+------------+--------------+-------------+----------+

Desire output:

+----------+-------------+------------+-------------+----------+-------------+------------+--------------+-------------+----------+
| a.ITEMID | a.WAREHOUSE | a.LOCATION | a.INVENTORY | b.ITEMID | b.WAREHOUSE | b.LOCATION | LOCATIONNAME | b.INVENTORY | VARIANCE |
+----------+-------------+------------+-------------+----------+-------------+------------+--------------+-------------+----------+
| ITEM001  | WHS001      | LOC001     | 5           | ITEM001  | WHS001      | T01        | TECH001      | 1           | -1       |
| ITEM001  | WHS001      | LOC001     | 0           | ITEM001  | WHS001      | T02        | TECH002      | 2           | 0        |
| ITEM001  | WHS001      | LOC001     | 0           | ITEM001  | WHS001      | T03        | TECH003      | 3           | 0        |
| ITEM002  | WHS001      | LOC002     | 4           | ITEM002  | WHS001      | T01        | TECH001      | 1           | 0        |
| ITEM002  | WHS001      | LOC002     | 0           | ITEM002  | WHS001      | T02        | TECH002      | 3           | 0        |
| ITEM003  | WHS001      | LOC003     | 2           | NULL     | NULL        | NULL       | NULL         | 0           | 2        |
+----------+-------------+------------+-------------+----------+-------------+------------+--------------+-------------+----------+
Thorsten Kettner
  • 89,309
  • 7
  • 49
  • 73
Alvin
  • 29
  • 5
  • 1
    If you just have `UNION` instead of `UNION ALL` the query will eliminate duplicates! p.s. welcome to the forum! :-) – Vérace Nov 02 '19 at 06:31
  • I do not know the data, buy you are comparing `ITEMID` with `MIN(INVENTORY)`, is it correct? – Farhad Rahmanifard Nov 02 '19 at 10:31
  • I suppose that getting duplicates is not your only problem here. The first query looks like an aggregation while it's not. Both `a.inventory` and `b.inventory` are in your `GROUP BY`. So, `MIN(a.INVENTORY)` is just `a.inventory` and `MIN(b.INVENTORY)` is just `b.inventory`. This makes the whole `GROUP BY` superfluous. – Thorsten Kettner Nov 02 '19 at 10:47
  • Please show us exactly what you want to select. Show sample data and expected result. What are the tables's keys? – Thorsten Kettner Nov 02 '19 at 10:48
  • @Thorsten i have added the details, please refer to the images i’ve attached. Thank u. – Alvin Nov 02 '19 at 11:09
  • The image is so small I cannot read it. Moreover, you should not link to images here. Please paste the data as text into your request instead. – Thorsten Kettner Nov 02 '19 at 11:10
  • Something to start with: Maybe it helps to understand what `GROUP BY` means: It means "result row per ___". E.g. `GROUP BY itemid` means "I want one result row per item". You'd get one row for item 123, one for item 234, etc. `GROUP BY warehouse` means "I want one result row per warehouse. You'd get one result row for warehouse A, one for warehouse B, etc. `GROUP BY itemid, warehouse` means "I want one result row per item and warehouse". With Item 123 in warehouses A and B and item 234 in warehouses A and C, you'd get four rows: 123/A, 123B, 234/A, 234/C. – Thorsten Kettner Nov 02 '19 at 11:11
  • Ok @Thorsten,i will update the details of my question.Thank u. – Alvin Nov 02 '19 at 11:18
  • I have formatted your request for you. It is quite some work, to get the tables aligned, so please do you do this work next time :-) You'd use a text editor and maybe a table formatting tool like https://www.tablesgenerator.com/text_tables. Put
     before the tables and 
    after them.
    – Thorsten Kettner Nov 02 '19 at 12:31
  • Thank u very much for your suggestion and effort.appreciate it @Thorsten.sorry for the trouble. – Alvin Nov 02 '19 at 12:35

2 Answers2

0

Welcome to SO! You should use UNION instead of UNION ALL.

Please, take a look at this question with full description of the difference.

Simon Osipov
  • 404
  • 5
  • 18
  • So you think the first query will have nulls in the a records, so there are duplicates with the second query? Or are you using `UNION` as a side effect, not really wanting to remove duplicates produced by unioning two queries, but for removing duplicates inside one (or each) of the queries? I don't like this answer, as you are kind of suggesting to fight symptoms with an extensive tool, rather than looking at the problem's roots. – Thorsten Kettner Nov 02 '19 at 11:01
0

You want to show table1 rows even when they have no match in table2. This is done with an outer join:

select
  t1.itemid,
  t1.warehouse,
  t1.location as t1_location,
  t1.inventory as t1_inventory,
  t2.location as t2_location,
  t2.locationname as t2_locationname,
  (t2.inventory, 0) as t2_inventory,
  t1.inventory - nz(t2.inventory, 0) as variance
from table1 as t1
left join table2 as t2 on t2.itemid = t1.itemid
order by t1.itemid;

I hope MS Access accepts this syntactically. MS Access is just horrible when it comes to SQL standard compliance.

You have the item's warehouse in both tables. Maybe you want to include it in the ON clause, maybe not. You decide :-)

Thorsten Kettner
  • 89,309
  • 7
  • 49
  • 73
  • Thank u for the help..i will try to run this in sql.running in ms access displays my required information but i’m having problem with duplicate amounts(next row) from table 1 – Alvin Nov 02 '19 at 13:56
  • I don't understand. This query would work for the sample data you have given, right? So, add sample data to your request, this query is having problems with. – Thorsten Kettner Nov 02 '19 at 15:40
  • In the desire output details you will see that inventory is not duplicate.. 1st line is 5 and 2nd and 3rd are both zero. And the variance is computed per line (which is technically correct) if table 1 inventory will not duplicate. Hopes this will explain my objective..sorry for the trouble. Thank u. – Alvin Nov 02 '19 at 17:28
  • Oh, I'm sorry. You are right, I didn't see this. What you are trying is complicated, even more so with MS Access. If you were using a good DBMS (Oracle, PostgreSQL, SQL Server, …) we would use window functions for this. But with MS Access this is not possible. In Access you'll need three queries that you glue together with two `UNION ALL`: one query for the first b row per item along with an aggregation over all its b rows, one query for the other b rows, and one for the items that have no match in b. – Thorsten Kettner Nov 02 '19 at 18:54
  • I see.i will try to use sql server but i need to study first since i’m not that good yet in sql server.. Thank u.. – Alvin Nov 03 '19 at 03:19