Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

laravel query builder with conditions

I am implementing a query to draw a multiple line chart using chartjs. I have an array of dates

["2016-10-16","2016-10-17","2016-10-18","2016-10-19","2016-10-20","2016-10-21","2016-10-22","2016-10-23","2016-10-24","2016-10-25","2016-10-26","2016-10-27","2016-10-28","2016-10-29","2016-10-30","2016-10-31","2016-11-01","2016-11-02","2016-11-03","2016-11-04","2016-11-05","2016-11-06","2016-11-07","2016-11-08","2016-11-09","2016-11-10","2016-11-11","2016-11-12","2016-11-13","2016-11-14","2016-11-15","2016-11-16"]

This array has dates between "2016-11-16" and "2016-10-16".

I have created a model Tickets, and I wrote a query to fetch tickets count grouped by tickets.status.

$join = $this->tickets();
$tickets = $join
         ->when($category, function($query) use ($category) {
             $ranges = $this->dateRange($category);
             return $query->whereBetween('tickets.created_at', $ranges);
         })
         ->select(DB::raw('COUNT(tickets.id) as tickets'), 'ticket_status.name as name', 'tickets.created_at')
         ->groupBy('ticket_status.name', 'tickets.created_at')
         ->get();

Executing this query I got

[
    {
        "tickets":"1",
        "name":"Closed",
        "created_at":"2016-11-08 14:07:32"
    },
    {
        "tickets":"1",
        "name":"Open",
        "created_at":"2016-11-08 14:07:32"
    },
    {
        "tickets":"1",
        "name":"Open",
        "created_at":"2016-11-11 12:24:39"
    },
    {
        "tickets":"1",
        "name":"Open",
        "created_at":"2016-11-11 12:26:38"
    },
    {
        "tickets":"1",
        "name":"Open",
        "created_at":"2016-11-11 12:27:04"
    },
    {
        "tickets":"1",
        "name":"Open",
        "created_at":"2016-11-11 12:27:49"
    },
    {
        "tickets":"1",
        "name":"Open",
        "created_at":"2016-11-11 12:28:47"
    },
    {
        "tickets":"1",
        "name":"Resolved",
        "created_at":"2016-11-08 14:07:32"
    }
]

If $label[0] != $tickets.created, ticket and name will be null but should have date

Please help me to get output like

[
    [
        'tickets'=>0,
        'name'=>null,//tickets don't have this date
        'created_at'=>'2016-10-16'
    ],
    [
        'tickets'=>0,
        'name'=>null,//tickets don't have this date
        'created_at'=>'2016-10-15'
    ],
    [
        'tickets'=>1,
        'name'=>'closed',//on this date 1 closed ticket
        'created_at'=>'2016-10-14'
    ],
    [
        'tickets'=>3,
        'name'=>'open',//on this date 3 open ticket
        'created_at'=>'2016-10-14'
    ],
    [
        'tickets'=>2,
        'name'=>'resolved',//on this date 2 resolved ticket
        'created_at'=>'2016-10-14'// on 2016-10-14 has three different tickets
    ],
    ...........
]

Please help me to find a solution. Thanks in advance.

like image 290
Manish Verma Avatar asked Nov 16 '16 13:11

Manish Verma


People also ask

Is query Builder faster than eloquent?

Eloquent ORM is best suited working with fewer data in a particular table. On the other side, query builder takes less time to handle numerous data whether in one or more tables faster than Eloquent ORM. In my case, I use ELoquent ORM in an application with tables that will hold less than 17500 entries.

What is the difference between Orm and query builder?

ORMs provide the highest form of abstraction and prevent typos not only in SQL keywords, but also in the table and column names. They take longer to get started than query builders — both, from a learning curve perspective and from the perspective of initial development overhead.

What is BelongsTo in Laravel?

BelongsTo is a inverse of HasOne. We can define the inverse of a hasOne relationship using the belongsTo method. Take simple example with User and Phone models. I'm giving hasOne relation from User to Phone. class User extends Model { /** * Get the phone record associated with the user.


3 Answers

Follow please Laravel:Collection:GroupBy

So it's maybe you need to have a code look like this

$join = $this->tickets();
$tickets = $join
         ->when($category, function($query) use ($category) {
             $ranges = $this->dateRange($category);
             return $query->whereBetween('tickets.created_at', $ranges);
         })
         ->select(DB::raw('COUNT(tickets.id) as tickets'), 'ticket_status.name as name', 'tickets.created_at')
         ->get()->groupBy(/** YOUR LOGIC HERE  **/);
like image 152
Yur Gasparyan Avatar answered Oct 23 '22 03:10

Yur Gasparyan


You'll need to convert this to Laravel/Eloquent, but this is a raw db query that does what you're looking for.

Assumed Tables / Data

Table: tbl_dates
id | date
1    2016-11-17 00:00:00
2    2016-11-18 00:00:00
...etc...

Table: tickets
id | created_at
1    2016-11-18 12:34:56
2    2016-11-18 01:23:45
3    2016-11-18 02:34:56

Table: ticket_status
ticket_id | name
1           Open
2           Closed
3           Closed

Query:

SELECT 
  COUNT(tickets.id) AS tickets,
  ticket_status.name, 
  DATE(tbl_dates.date) AS ticket_date
FROM 
  tbl_dates
LEFT JOIN 
  tickets 
ON
  (DATE(tbl_dates.date) = DATE(tickets.created_at))
LEFT JOIN
  ticket_status
ON
  (tickets.id = ticket_status.ticket_id)
GROUP BY 
  ticket_status.name
ORDER BY 
  ticket_date
ASC

Result:

 tickets | name | ticket_date
 0         NULL   2016-11-17
 1         Open   2016-11-18
 2         Closed 2016-11-18

Basically, to do this in pure MySQL you need a table with all dates. Check out this SO post for an easy way to generate the dates table.

like image 29
SoWizardly Avatar answered Oct 23 '22 04:10

SoWizardly


Use MySQL's date function to format the date first and then group by the formatted date:

So your query should look something like this:

$join = $this->tickets();
    $tickets = $join
            ->when($category, function($query) use ($category) {
                $ranges = $this->dateRange($category);
                return $query->whereBetween('tickets.created_at', $ranges);
            })
            ->select(DB::raw('COUNT(tickets.id) as tickets'), 'ticket_status.name as name', DB::raw('DATE('tickets.created_at') as created_date'))
            ->groupBy('ticket_status.name', 'created_date')
            ->get();
like image 1
Marlon Dyck Avatar answered Oct 23 '22 04:10

Marlon Dyck