Reputation: 154
I have a form where my users can set Criteria to search their customer database, however I am struggling to pull the query together for this (working in Laravel 5.7).
Currently the criteria customers can set is as follows:
I am now trying to get my head around how I can build this into a query, I can’t even produce a tangible example! My hurdle seems to be checking the first record & the last record to make sure it meets the criteria.
SQLFiddle: http://sqlfiddle.com/#!9/68407/1
My Table:
| id | name | email | provider | created_at
---------------------------------------------------------------------------------------
| 1 | Mr Smith | [email protected] | facebook | 2018-11-01 09:00:00 |
| 2 | Mrs Smith | [email protected] | facebook | 2018-11-01 09:00:00 |
| 3 | Miss Smith | [email protected] | email | 2018-11-01 09:00:00 |
| 4 | Doctor Smith | [email protected] | email | 2018-11-01 09:00:00 |
| 5 | Lord Smith | [email protected] | twitter | 2018-11-01 09:00:00 |
| 6 | Lady Smith | [email protected] | email | 2018-11-01 09:00:00 |
| 7 | Mr Smith | [email protected] | facebook | 2018-11-02 09:00:00 |
| 8 | Mrs Smith | [email protected] | facebook | 2018-11-02 09:00:00 |
| 9 | Doctor Smith | [email protected] | email | 2018-11-02 09:00:00 |
| 10 | Lord Smith | [email protected] | twitter | 2018-11-02 09:00:00 |
| 11 | Lady Smith | [email protected] | email | 2018-11-02 09:00:00 |
| 12 | Mr Smith | [email protected] | facebook | 2018-11-03 09:00:00 |
| 13 | Mrs Smith | [email protected] | facebook | 2018-11-03 09:00:00 |
| 14 | Miss Smith | [email protected] | email | 2018-11-03 09:00:00 |
| 15 | Lord Smith | [email protected] | twitter | 2018-11-03 09:00:00 |
| 16 | Lady Smith | [email protected] | email | 2018-11-03 09:00:00 |
Example customer criteria for the query:
Current query:
$Customers = Customer::groupBy('email')
->havingRaw('COUNT(*) > 2’)
->where('created_at', '<', Carbon::now()->subDays(2)->toDateTimeString())
->get();
I can’t figure out how to pull the first customer record check that it more than 2 days old, and then pull their last record and make sure it is more than 1 day old. I know that my current query is completely useless for what I am trying to achieve, but again I am struggling to pull this together.
Expected results:
| id | name | email | provider | created_at
---------------------------------------------------------------------------------------
| 12 | Mr Smith | [email protected] | facebook | 2018-11-03 09:00:00 |
| 13 | Mrs Smith | [email protected] | facebook | 2018-11-03 09:00:00 |
Upvotes: 0
Views: 421
Reputation: 38952
The SQL query in the MySQL dialect to make that selection is as follow
SELECT id, name, email, provider, created_at
FROM customers
WHERE provider = 'facebook'
GROUP BY email
HAVING
count(*) > 2
AND min(created_at) < date_sub(now(), interval 2 day)
AND max(created_at) < date_sub(now(), interval 1 day)
That can be translated as an Eloquent query like so
$havingClause = 'count(*) > ? AND min(created_at) < ? AND max(created_at) < ?';
$havingClauseBindings = [
2,
Carbon::now()->subDays(2)->toDateTimeString(),
Carbon::now()->subDays(1)->toDateTimeString()
];
$customers = Customer::where('provider', 'facebook')
->groupBy('email')
->havingRaw($havingClause, $havingClauseBindings)
->get();
Upvotes: 1
Reputation: 321
The query you are looking for is:
select * from customers group by email having count(*) > 2 and min(created_at) <= '2018-10-02 09:00:00' and max(created_at) <= '2018-10-03 09:00:00' and provider = 'facebook'
assuming the current time is 2018-10-04 09:00:00.
In eloquent:
$Customers = Customer::groupBy('email')
->havingRaw('COUNT(*) > 2')
->havingRaw('max(created_at) < ?' , [Carbon::now()->subDays(2)->toDateTimeString()])
->havingRaw('min(created_at) < ?' , [Carbon::now()->subDays(1)->toDateTimeString()])
->havingRaw('provider = ?' , ['facebook'])
->get();
On a separate note, using eloquent you can chain methods, like the following
$customers = Customer::groupBy('email');
if( $includeCount ) {
$customers->havingRaw('COUNT(*) > 2');
}
...
...
...
Upvotes: 2