I’m trying to get all of a users completed habits, although I’m getting a syntax issue when using eloquent?
What’s going on here… syntax seems fine to me.
Query:
$completedHabits = Habit::query()
->where('user_id', auth()->user()->id)
->join('habit_goals', 'habits.id', '=', 'habit_goals.habit_id')
->whereHas('progressLogs', function($q) {
$q
->whereRaw('created_at >= SUBTIME(created_at, INTERVAL habit_goals.interval SECOND)')
->select(DB::raw('SUM(value) as valueCommited'))
->havingRaw('valueCommited > habit_goals.value');
})
->orderBy('habit_goals.created_at', 'DESC')
->get();
Full error:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘) having valueCommited > habit_goals.value) order by habit_goals
.created_at
‘ at line 1
2
Answers
The mistake you’re encountering arises from a common error in employing the
havingRaw
clause within Laravel Eloquent. The problem stems from your attempt to utilize the aliasvalueCommited
in thehavingRaw
clause, but this alias isn’t recognized at that juncture within the query.To rectify this issue, you can employ a subquery to compute the
valueCommited
and then reference it within thehaving
clause. Here’s how you can adjust your query to address this problem:In this revised query, I’m utilizing the
selectSub
method to construct a subquery that calculates thevalueCommited
. The subquery computes the sum of values for each habit, comparing it to thehabit_goals.value
and ensuring that it exceeds this value. This subquery is subsequently given the aliasvalueCommited
, which can then be used in theorderBy
clause of the primary query.The error you’re encountering is due to a MySQL syntax issue in your query. Specifically, the error is happening because you’re using the havingRaw method with an alias (valueCommited) that is calculated within a subquery.
In MySQL, you cannot reference aliases defined in the SELECT clause in the HAVING clause directly. To work around this, you need to wrap the entire query in a subquery and then reference the alias in the outer query’s HAVING clause.
Here’s the modified query: