Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

sargbah84's avatar

How to Get All Orders of Customers Assigned to a Specific Agent Using Query Builder

Hey guys, I've been pulling my hair strings for days trying to write this query but just not getting anywhere. I have these tables:

Agents (Users)
    id
    name
    email
    password
    created_at
    updated_at

Customers
    id
    agent_id
    firstname
    lastname
    email
    created_at
    updated_at

Orders
    id
    customer_id
    product_id
    amount

Customer_Tags
    id
    customer_id
    name

Products
    id
    name

I need to write a SQL statement that get all Orders of Customers who are assigned to the current logged in user (by agent_id) and has this tag (ID: 234) but not any of these tags [3343, 445, 333] and has purchased any of these product (IDs: 18, 33, 29).

Just so you understand what tags do. Customers are tagged based on the actions they takes. This is done for marketing purposes. If a customer purchase a product, that customer gets a specific tag attached to them. If they go on to do take another actions like watching the webinar, there's another tag attached and on and on.

This is what I have written.

return DB::table('orders')
            ->join('customers', 'orders.custom_id', '=', 'customers.id')
              ->join('customer_tags', function ($join) {
                  $join->on('customers.id', '=', 'customer_tags.custom_id')
                    ->whereIn('customer_tags.id', [234])
                      ->whereNotIn('customer_tags.id', [3343, 445, 333]);
                  })
                  ->join('products', 'products.id', '=', 'orders.product_id')
                    ->whereIn('orders.product_id', [18, 33, 29])
                      ->where('customers.agent_id', Auth::user()->id)
                        ->select('orders.invoice_at', 'customers.*', 'products.name')
                          ->get();

Unfortunately, when I customer has 234 and also has any of these tags (3343, 445, 333), it's pulling them into the records. Please help. Thanks

0 likes
8 replies
jlrdw's avatar

I would look at using eloquent for that, and eloquent has all of the query Builder methods.

sargbah84's avatar

@jlrdw Thanks but I tried Eloquent but didn't couldn't get anywhere. I only came far using Query builder.

jlrdw's avatar

I don't know your data, but first look at reducing the query as much as possible,

->whereIn('customer_tags.id', [234])
                      ->whereNotIn('customer_tags.id', [3343, 445, 333]);

if all you need is 234, can't you just select that. Do you really need whereNotIn.

Also do you have a good query visual designer. Maybe a query you need might be better suited for the db facade.

A good example : https://laracasts.com/discuss/channels/laravel/sql-native-to-query-builder

Or consider learning eloquent better and learn eloquent relations.

sargbah84's avatar

@jlrdw Please re-read the full details of the question. I did provide the data structure and what I'm trying to achieve. I do know a few things about Eloquent but this is more complicated than writing two 'where' statements.

I need to write a SQL statement that get all Orders of Customers who are assigned to the current logged in user (by agent_id) and has this tag (ID: 234) but not any of these tags [3343, 445, 333] and has purchased any of these product (IDs: 18, 33, 29).

It's a must that I include orders of contacts that have a certain tag but don't have certain tags. One contact can have all of the listed tags listed in the have and don't have tags.

jlrdw's avatar

Bear in mind, a complex query can take time and trial and error.

Try other things, like:

->whereBetween('customer_tags.id', [233, 235])

Just start redoing small things in the query one at a time as needed. No one just whips a query like that out the first try.

I cannot figure out why the whereIn / whereNotIn combo isn't working.

Sometimes the order of statements matter: https://stackoverflow.com/questions/27919603/laravel-wherenotin-and-where-not-working-together-together

design_studio's avatar

Can you try the following (It is not test, since i haven't got the code):

App\Order::whereHas('customers', function (Builder $query) {
    $query->where('agent_id', Auth::id());
})
->whereHas('customers.tags', function (Builder $query) {
    $query->where('id', 243);
})
->whereDoesntHave('customers.tags', function (Builder $query) {
    $query->whereNotIn('id', [3343, 445, 333]);
})
->whereHas('products', function (Builder $query) {
    $query->whereIn('id', [18, 33, 29]);
})
->get();
design_studio's avatar

You are right. I think it could actually work with whereHas. Like this:

App\Order::whereHas('customers', function (Builder $query) {
    $query->where('agent_id', Auth::id());
})
->whereHas('customers.tags', function (Builder $query) {
    $query->where('id', 243)->whereNotIn('id', [3343, 445, 333]);
})
->whereHas('products', function (Builder $query) {
    $query->whereIn('id', [18, 33, 29]);
})
->get();

I am not sure this will result in what you want since i think this will not give you customers without tags at all. for that maybe you need to add statement that adds customers with no tags at all.

May be like this:

App\Order::whereHas('customers', function (Builder $query) {
    $query->where('agent_id', Auth::id());
})
->whereHas('customers.tags', function (Builder $query) {
    $query->where('id', 243)->whereNotIn('id', [3343, 445, 333]);
})
->doesntHave('customers.tags', 'or')
->whereHas('products', function (Builder $query) {
    $query->whereIn('id', [18, 33, 29]);
})
->get();

Please or to participate in this conversation.