简体   繁体   中英

Merging two tables without using join in mysql?

I have done an unsuccessful attempt to merge values from two different tables.The first one displays just as I would like but the 2nd one displays only the first row every time.

Select * From (Select date as Date, Sum(qty) as qtySum, Sum(weight) 
as weightSum From stock_list Group by date) as A,
(Select Sum(weight) as weightSum,Count(barcode)
as barcodeCount From selected_items Group by date) as B Group by date;

This is the output that I get.

在此处输入图片说明

These is my selected_items table.

在此处输入图片说明

This is my stock_list. 在此处输入图片说明

Both my queries work individually and I get the correct output only when I try to run them together it gives a problem for the 2nd query.Can anyone point out my mistake or show me a better way to do it. This is what my final objective is 在此处输入图片说明

The first problem is that you are grouping by date in your subquery B , but you don't select it, so your result set might be something like:

weightSum       barcodeCount
---------------------------
26              8
9               14
4               7

This is the result for 3 dates, but you have no idea which date which row refers to.

Your next problem is that you are using a cross join, because there is no link between your two queries, this means if your first query returns:

Date            qtySum      weightSum
----------------------------------------
2016-01-20      1           1
2016-01-21      2           2

After you have done this cross join you end up:

Date            qtySum      a.weightSum     b.weightSum     barcodeCount
--------------------------------------------------------------------------
2016-01-20      1           1               26              8
2016-01-20      1           1               9               14
2016-01-20      1           1               4               7
2016-01-21      2           2               26              8
2016-01-21      2           2               9               14
2016-01-21      2           2               4               7

So every row from A is matched with every row from B giving you 6 total rows.

Your third problem is that you then group by date, but don't perform any aggregates, without delving too much into the fine print of the SQL Standard, the group by clause, and functional dependency, lets simplify it to MySQL allows this, but you shouldn't do it unless you understand the limitations (This is covered in more detail on this in this answer ). Anything in the select that is not in a group by clause should probably be within an aggregate.

So, due to MySQL's GROUP BY Extension by selecting everything and grouping only by date, what you are effectively saying is take 1 row per date, but you have no control over which row, it might be the first row from each group as displayed above, so the result you would get is:

Date            qtySum      a.weightSum     b.weightSum     barcodeCount
--------------------------------------------------------------------------
2016-01-20      1           1               26              8
2016-01-21      2           2               26              8

Which I think is why you are ending up with all the same values from the subquery B repeated.

So that covers what is wrong, now on to a solution, assuming there will be dates in stock_list that don't exist in selected_items , and vice versa you would need a full join, but since this is not supported in MySQL you would have to use UNION , the simplest way would be:

SELECT  t.Date,
        SUM(t.StockQuantity) AS StockQuantity, 
        SUM(t.StockWeight) AS StockWeight, 
        SUM(t.SelectedWeight) AS SelectedWeight, 
        SUM(t.BarcodeCount) AS BarcodeCount
FROM    (   SELECT  date, 
                    SUM(qty) AS StockQuantity, 
                    SUM(weight) AS StockWeight, 
                    0 AS SelectedWeight, 
                    0 AS BarcodeCount
            FROM    stock_list
            GROUP BY Date
            UNION ALL
            SELECT  date, 
                    0 AS StockQuantity, 
                    0 AS StockWeight, 
                    SUM(weight) AS SelectedWeight, 
                    COUNT(BarCode) AS BarcodeCount
            FROM    selected_items
            GROUP BY Date
        ) AS t
GROUP BY t.Date;

EDIT

I can't test this, nor am I sure of your exact logic, but you can use variables to calculate a running total in MySQL . This should give an idea of how to do it:

SELECT  Date,
        StockQuantity,
        StockWeight,
        SelectedWeight,
        BarcodeCount,
        (@w := @w + StockWeight -  SelectedWeight) AS TotalWeight,
        (@q := @q + StockQuantity - BarcodeCount) AS TotalQuantity
FROM    (   SELECT  t.Date,
                    SUM(t.StockQuantity) AS StockQuantity, 
                    SUM(t.StockWeight) AS StockWeight, 
                    SUM(t.SelectedWeight) AS SelectedWeight, 
                    SUM(t.BarcodeCount) AS BarcodeCount
            FROM    (   SELECT  date, 
                                SUM(qty) AS StockQuantity, 
                                SUM(weight) AS StockWeight, 
                                0 AS SelectedWeight, 
                                0 AS BarcodeCount
                        FROM    stock_list
                        GROUP BY Date
                        UNION ALL
                        SELECT  date, 
                                0 AS StockQuantity, 
                                0 AS StockWeight, 
                                SUM(weight) AS SelectedWeight, 
                                COUNT(BarCode) AS BarcodeCount
                        FROM    selected_items
                        GROUP BY Date
                    ) AS t
            GROUP BY t.Date
        ) AS t
        CROSS JOIN (SELECT @w := 0, @q := 0) AS v
GROUP BY t.Date;

You could use a join . However, if the set of dates is not the same in both tables, then you would want a full outer join . But that is not available in MySQL. Instead:

select date, sum(qtySum), sum(weightsum1), sum(weightsum2), sum(barcodeCount)
from ((Select date as Date, Sum(qty) as qtySum, Sum(weight) as weightSum1,
              NULL as weightsum2, NULL as barcodeCount
        From stock_list
        Group by date
       ) union all
       (Select date, null, null, Sum(weight), Count(barcode) as barcodeCount 
        From selected_items
        Group by date
       )
      ) t
Group by date;

I'm not sure how your desired output corresponds to the query you have provided. But this should aggregate and combine the data from the two tables by date, so you can finalize the query.

You can use FULL JOIN operator to solve your task if some dates may not exists in both tables.

Select ISNULL(A.date, B.date) AS date,
       A.qtySum,
       A.weightSum,
       B.weightSum,
       B.barcodeCount
From 
    (Select date as Date, 
            Sum(qty) as qtySum, 
            Sum(weight) as weightSum 
     From stock_list 
     Group by date) as A
FULL JOIN
(Select date,
        Sum(weight) as weightSum,
        Count(barcode) as barcodeCount 
 From selected_items 
 Group by date) as B ON A.date = B.date

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