简体   繁体   中英

After joining two queries (each having different columns) with UNION I'm getting only one column

I have joined two queries with UNION keyword (Access 2016). It looks like that:

SELECT ITEM.IName, Sum(STOCK_IN.StockIn) AS SumOfIN
FROM ITEM INNER JOIN STOCK_IN ON ITEM.IName = STOCK_IN.IName
GROUP BY ITEM.IName
UNION SELECT ITEM.IName, Sum(STOCK_OUT.StockOut) AS SumOfOut
FROM ITEM INNER JOIN STOCK_OUT ON ITEM.IName = STOCK_OUT.IName
GROUP BY ITEM.IName

I get the following result:

IName | SumOfIN
----------------
Abis Nig | 3

Abrotanum | 1

Acid Acet | 2

Aconite  Nap |  2

Aconite  Nap |  3

Antim Crud |    3

Antim Tart |    1

But I want the following result:

IName | SumOfIN | SumOfOut
----------------

Abis Nig | 3 | 0

Abrotanum | 1 | 0

Acid Acet | 2 | 0

Aconite  Nap | 2 | 3

Antim Crud | 0 | 3

Antim Tart | 0 | 1

Can anyone tell me what changes should I make here?

You need to add dummy values for the third column where they don't exist in the table you are UNION ing. In addition, you need an overall SELECT/GROUP BY since you can have values for both StockIn and StockOut:

SELECT IName, SUM(SumOfIN), Sum(SumOfOut) 
FROM (SELECT ITEM.IName, Sum(STOCK_IN.StockIn) AS SumOfIN, 0 AS SumOfOut
      FROM ITEM INNER JOIN STOCK_IN ON ITEM.IName = STOCK_IN.IName
      GROUP BY ITEM.IName
      UNION ALL
      SELECT ITEM.IName, 0, Sum(STOCK_OUT.StockOut)
      FROM ITEM INNER JOIN STOCK_OUT ON ITEM.IName = STOCK_OUT.IName
      GROUP BY ITEM.IName) s
GROUP BY IName

Note that column names in the result table are all taken from the first table in the UNION , so we must name SumOfOut in that query.

You can do this query without UNION at all:

select i.iname, si.sumofin, so.sumofout
from (item as i left join
      (select si.iname, sum(si.stockin) as sumofin
       from stock_in as si
       group by si.iname
      ) as si
      on si.iname = i.iname
     ) left join
     (select so.iname, sum(so.stockout) as sumofout
      from stock_out as so
      group by so.iname
     ) as so
     on so.iname = i.iname;

This will include items that have no stock in or stock out. That might be a good thing, or a bad thing. If a bad thing, then add:

where si.sumofin > 0 or so.sumofout > 0

If you are going to use union all , then you can dispense with the join to items entirely:

SELECT IName, SUM(SumOfIN), Sum(SumOfOut) 
FROM (SELECT si.IName, Sum(si.StockIn) AS SumOfIN, 0 AS SumOfOut
      FROM STOCK_IN as si
      GROUP BY si.INAME
      UNION ALL
      SELECT so.IName, 0, Sum(so.StockOut)
      STOCK_OUT so 
      GROUP BY so.IName
     ) s
GROUP BY IName;

The JOIN would only be necessary if you had stock items that are not in the items table. That would be a sign of bad data modeling.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM