Search code examples
mysqlself-joincorrelated-subquery

Cant figure out self join query


I have a table with the following structure.

+-----------------------+--------------+------+-----+---------+-------+
| Field                 | Type         | Null | Key | Default | Extra |
+-----------------------+--------------+------+-----+---------+-------+
| linq_order_num        | char(32)     | NO   | PRI | NULL    |       |
| order_status_id       | int(11)      | YES  | MUL | NULL    |       |
| order_id              | varchar(100) | YES  |     | NULL    |       |
| item_name             | varchar(120) | YES  |     | NULL    |       |
| item_cost             | float        | YES  |     | NULL    |       |
| custmer_id            | int(11)      | YES  | MUL | NULL    |       |
| order_date_time       | datetime     | YES  |     | NULL    |       |
| order_category        | varchar(120) | YES  |     | NULL    |       |
| ordered_by            | int(11)      | YES  | MUL | NULL    |       |
| linq_shipping_cost    | float        | YES  |     | NULL    |       |
| website_shipping_cost | float        | YES  |     | NULL    |       |
| total_cost            | float        | YES  |     | NULL    |       |
| advance_amount        | float        | YES  |     | NULL    |       |
| website               | varchar(120) | YES  |     | NULL    |       |
| other                 | varchar(120) | YES  |     | NULL    |       |
| rvn                   | int(11)      | YES  |     | NULL    |       |
| received_date         | datetime     | YES  |     | NULL    |       |
| delivered_date        | datetime     | YES  |     | NULL    |       |
| store_id              | int(11)      | YES  | MUL | NULL    |       |
+-----------------------+--------------+------+-----+---------+-------+

So for every day I need to find the total order cost.I can get it by using this query.

select sum(total_cost), date_format(order_date_time,"%Y-%m-%d") from 
       order_item group by date_format(order_date_time,"%Y-%m-%d")

Also I need the total remaining amount paid on the delivered dates.

select sum(total_cost-advance_amount),date_format(delivered_date,"%Y-%m-%d")
       from order_item group by date_format(delivered_date,"%Y-%m-%d")

Not all the days, orders will happen and not all the days deliveries will happen.If there is day with no orders the total cost for that day should be shown as zero and the total remaining amount shown should be sum of (total_cost-advance_amount) for the day.

Is there a way I could combine the above two queries in one query and get the result?

So to summarise for a particular day d: I need sum(total_cost) where ordered_date_time = d , I need sum(total_cost -advance_amount) where delivered_date = d Essentially looking for a table like this:

Date            Total Cost          Total Delivery Amounts
d                 500                     2000
d1                0                       900
d2                900                     0 

I tried using a subquery. The problem is it doesn't display the cases for d1, where is total cost for that day is 0.

Query:

select
    date_format(order_date_time,"%Y-%m-%d") date,
    sum(total_cost) total,
    sum(advance_amount) advance_amount,
    IFNULL( (select sum(total_cost-advance_amount)
from order_item a 
where date_format(a.delivered_date,"%Y-%m-%d") = date_format(d.order_date_time,"%Y-%m-%d") ),0 ) delivery_amount
from order_item d
group by date_format(order_date_time,"%Y-%m-%d"), delivery_amount

Solution

  • You can use your two queries as derived tables and join them on date. The problem is, that you would need a FULL OUTER JOIN, which is not supported by MySQL. So you first need to extract all the dates from both columns

    select date(order_date_time) as d from order_item
    union
    select date(delivered_date)  as d from order_item
    

    und use a left join with your queries

    select
        dates.dt,
        coalesce(tc.total_cost, 0),
        coalesce(tm.total_remaining, 0)
    from (
        select date(order_date_time) as dt from order_item
        union
        select date(delivered_date)  as dt from order_item
    ) dates
    left join (
         select sum(total_cost) as total_cost, date(order_date_time) as dt
         from order_item
         group by dt
    ) tc using(dt)
    left join (
         select sum(total_cost-advance_amount) as total_remaining, date(delivered_date)
         from order_item
         group by dt
    ) tm using(dt)
    

    I also replaced date_format(..) with date(..). You can format the dates in the outer select or in your application.