1

I have 3 tables called cash_manages, outlets, and delivery_boys the structure is

        //outlets
        id name
        1  utha
        2  alabama

        //delivery_boys
        id outlet_id  name
        1     1       John 
        2     1       Mike
        3     2       Alex

        //cash_manage
        id   source_type   source_id   destination_id   status     amount
        1      admin          1             2            give       500 
        2      admin          2             1            give       350   
        3      deliveryBoy    1             2            receive    300 
        4      admin          2             2            give       500
        5      admin          2             1            give       800 
        6      user           1             1            give       600
        7      user           2             2            give       450

   //the logic
    1-> if source_type is admin then the source_id is outlet_id and the cash is **GIVEN** to destination_type delivery_boy_id

    2-> if source_type is deliveryBoy then the source_id is delivery_boy_id and the cash is **Received** by destination_type outlet_id(admin)

I want to get the result as below in the view (the cash with delivery boy)

num   outlet   delivery_boy   cash_taken  cash_returned  cash_has 
1     alabama     John          1150          300          1050
2     alabama     mike          500           0            500

I joined all three tables and able to get the Outlet Name and Delivery Boy Name. Now i am stuck at calculation part

public function index(Request $request) 
{
    $outlet_id = $request->outlet_id;

    $transaction_list = DeliveryCashManage::leftJoin('outlets','outlets.id','delivery_cash_manages.source_id')
                                          ->leftJoin('delivery_boys','delivery_boys.id','destination_id')
                                          ->where('source_type', 'admin')
                                          ->where('source_id', $outlet_id)
                                          ->select('delivery_cash_manages.id','outlets.name as outlet','delivery_boys.name as delivery_boy','amount')
                                          ->groupBy('delivery_boys.name')
                                          ->get();

    return view('pages.manager.cash');
}

i'm getting the following error

SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'ideal_chicken.delivery_cash_manages.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by (SQL: select `delivery_cash_manages`.`id`, `outlets`.`name` as `outlet`, `delivery_boys`.`name` as `delivery_boy`, `amount` from `delivery_cash_manages` left join `outlets` on `outlets`.`id` = `delivery_cash_manages`.`source_id` left join `delivery_boys` on `delivery_boys`.`id` = `destination_id` where `source_type` = admin and `source_id` = 1 group by `destination_id`)

I think my query or logic is wrong, please need some help in fixing this

thank you

Mr Robot
  • 887
  • 4
  • 18
  • 47
  • 1
    Possible duplicate of [Error related to only\_full\_group\_by when executing a query in MySql](https://stackoverflow.com/questions/34115174/error-related-to-only-full-group-by-when-executing-a-query-in-mysql) – aynber Aug 17 '17 at 15:21
  • thanks for your response really appreciate it, how do i do the calculations of `cash_taken`, `cash_returned`. thank you – Mr Robot Aug 17 '17 at 15:23
  • This is a little confusing when the source type is admin, the source id becomes the destination id on the outlets table which is fine. But the cash is given to destination_type delivery_boy_id... What is destination_type referring to? Is that another table? I'm not sure how to connect an admin record to a delivery boy exactly. Also, the results you are looking for are the actual results? Or is it just an example of what you are looking for and the specific numbers are made up? – user1669496 Aug 17 '17 at 15:30
  • 1
    Also it doesn't seem your left joins are following your own rules. You say the source_id is the delivery_boy_id when the source type is deliveryBoy but you are joining these two tables on delivery_boys.id = destination_id – user1669496 Aug 17 '17 at 15:34
  • @user3158900 thanks for the response, if the `source_type` is `admin` then `source_id` is `outlet_id` and the destination_id is `delivery_boy_id`. if `source_type` is `deliveryBoy` the `source_id` is `delivery_boy_id` the destination_id will be `outlet_id`. – Mr Robot Aug 17 '17 at 15:35
  • @user3158900 the joins are fine, i am getting the proper `delivery_boy_name` and the `outlet_name` all i'm worried is about how to calculate the `cash_taken` `cash_returned`, thank you – Mr Robot Aug 17 '17 at 15:39
  • They might look fine but the problem is you are doing `where source_type = 'admin'` to get there which is going to end up throwing everything off because we also need to include data `where source_type = 'deliveryBoy'` in our calculations so we cant do that. I'm pretty close to the solution but I can't figure out how you are coming up with `cash_has` – user1669496 Aug 17 '17 at 17:14

1 Answers1

1

This isn't the complete answer but it's close. No matter how I work the data though, I can't figure out how you are coming up with cash_has. Also I'm keeping it raw SQL because I feel it would be more helpful and shouldn't be difficult to convert back to query builder. I also don't know the exact column names so you may have to fix some of those.

SELECT
    COALESCE(outlets_admin.name, outlets.name) AS outlet, 
    COALESCE(boys_admin.name, boys.name) AS delivery_boy,
    SUM(IF(cm.source_type = 'admin', amount, 0)) AS cash_taken,
    SUM(IF(cm.source_type = 'deliveryBoy', amount, 0)) AS cash_returned,
    SUM(IF(cm.source_type = 'admin', amount, 0)) - SUM(IF(cm.source_type = 'deliveryBoy', amount, 0)) AS cash_has
FROM delivery_cash_manages cm
LEFT JOIN outlets ON outlets.id = cm.destination_id AND cm.source_type = 'deliveryBoy'
LEFT JOIN delivery_boys boys ON boys.id = cm.source_id AND cm.source_type = 'deliveryBoy'
LEFT JOIN outlets outlets_admin ON outlets_admin.id = cm.source_id AND cm.source_type = 'admin'
LEFT JOIN delivery_boys boys_admin ON boys_admin.id = cm.destination_id AND cm.source_type = 'admin'
WHERE COALESCE(outlets.id, outlets_admin.id) = '2'  #  This is where you plug in your $outlet_id
GROUP BY outlet, delivery_boy

The reason you are getting an error with your query though is if you group by anything, you need to group by everything you select which are aren't aggregate columns (functions like sum, max, avg).

user1669496
  • 32,176
  • 9
  • 73
  • 65
  • thank you so much i really appreciate your time, i'l try it out – Mr Robot Aug 18 '17 at 05:20
  • `cash_has` means the cash with the delivery boy, if we **subtract** the `cash_taken` and `cash_returned` shouldn't we get `cash_has`. thank you – Mr Robot Aug 18 '17 at 05:31
  • for `cash_has` i did `abs(SUM(IF(cm.source_type = 'admin', amount, 0)) - SUM(IF(cm.source_type = 'deliveryBoy', amount, 0))) AS cash_has` and i'm getting expected result. the thing is are there any **scenarios** where the **query** might give wrong result. thank you – Mr Robot Aug 18 '17 at 06:19
  • the query is working fine, but there are multiple `delivery_boys` under one `outlet` so if we **GROUP BY** the **OUTLET** we will be getting only one delivery boys details so tried by removing OUTLET in GROUP BY i'm getting error`Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column`, can you please guide me through – Mr Robot Aug 18 '17 at 06:43
  • 1
    That statement is false, you can group by outlet and get results for multiple delivery boys (as long as you are also grouping by delivery boys, which we are doing). However if you are sure you want to remove that group by, then you also need to remove the select for outlet and you should stop getting that error. – user1669496 Aug 18 '17 at 13:22
  • 1
    I've updated my answer to include `cash_has`. I kind of thought that might be what you were looking for but it didn't match up with your expected results of 1050/500. Unless some details were left out, this query should be correct although it wouldn't hurt to remove that where clause and manually check the numbers to make sure it's correct. – user1669496 Aug 18 '17 at 13:31
  • thank you so much for you time, this query works totally fine if a outlet has only one delivery boy, but if more than one i'm getting only one record. i think i'll have to figure out a somehow. thank you though – Mr Robot Aug 18 '17 at 13:45
  • 1
    That's really strange because I put the data you've given in some tables I've made, and running my query, I am seeing data for both John and Mike in Alabama. If I remove the where, I can also see data for Mike in utha – user1669496 Aug 18 '17 at 13:48
  • may be the data that i have might be wrong, i'll look in to it. and again thank you so much i really appreciate it – Mr Robot Aug 18 '17 at 13:50
  • hi i'm stuck wit new field here, how do i get the `cash_taken` by adding the user `amount` also(cash_admin+cash_user = cash_taken), i tried `SUM(IF(cm.source_type = 'admin', amount, 0)) + SUM(IF(cm.source_type = 'user', amount, 0))AS cash_taken,` but i'm getting only admin `amount` user `amount` is returning 0. thank you – Mr Robot Sep 03 '17 at 13:45