sql query last_messages displays wrong message - sql

i have query like this, but displays wrong last_message.
$users = Message::join('users', function ($join) {
$join->on('messages.from_id', '=', 'users.id')
->orOn('messages.to_id', '=', 'users.id');
})
->where(function ($q) {
$q->where('messages.from_id', auth()->user()->id)
->orWhere('messages.to_id', auth()->user()->id);
})
->where('users.id','!=',auth()->user()->id)
->select([
'users.id',
'users.name',
'users.avatar',
DB::raw('MAX(messages.created_at) max_created_at'),
DB::raw('MAX(messages.body) last_message'),
DB::raw('CASE WHEN(COUNT(messages.is_read) FILTER (WHERE is_read = false
AND messages.from_id != '.auth()->user()->id.') = 0) THEN true ELSE false END is_read'),
DB::raw('COUNT(messages.is_read) FILTER (WHERE is_read = false
AND messages.from_id != '.auth()->user()->id.') count_unread')
])
->orderBy('max_created_at', 'desc')
->groupBy('users.id')
->paginate($request->per_page ?? 20)
->withQueryString();
when i change
DB::raw('MAX(messages.body) last_message'),
to
DB::raw('messages.body ORDER BY messages.created_at DESC LIMIT 1 last_message'),
display error messages like this, syntax error at or near "last_message". How to fix this?

You want to alias the column, not the statement. Try to change it to:
messages.body last_message ORDER BY messages.created_at DESC LIMIT 1

So you need first order the records based on some column and then return the first record of that list.
$cart_data = ScCart::orderBy('created_at', 'asc')->first();
$cart_data = ScCart::orderBy('created_at', 'desc')->first();
This will work for first and last record created in that table.

Related

SELECT DISTINCT ON expressions must match initial ORDER BY expressions in typeorm query

I have a query that I want get rows with unique item_id and sort them according to timestamp.
But I get this error everytime from this code
const boxPreviewActivities = await this.activityLogEntryRepository
.createQueryBuilder('activityLogEntry')
.where("activityLogEntry.activity = 'BOX_PREVIEW'")
.andWhere('activityLogEntry.projectId = :projectId', { projectId })
.andWhere('activityLogEntry.userSub = :userSub', { userSub: user?.sub })
.andWhere((qb) => {
const subQuery = qb
.subQuery()
.select(
"DISTINCT activityLogEntry.originalData ::jsonb -> 'source' ->> 'item_id'"
)
.from(ActivityLogEntryEntity, 'activityLogEntry')
.where("activityLogEntry.activity = 'BOX_DELETE'")
.getQuery();
return `activityLogEntry.originalData ::jsonb -> 'source' ->> 'item_id' NOT IN (${subQuery})`;
})
.distinctOn([
"activityLogEntry.originalData ::jsonb -> 'source' ->> 'item_id' ",
])
.orderBy('activityLogEntry.timestamp', 'DESC')
.limit(limitNumber)
.getMany();
return boxPreviewActivities;
}
** ERROR [ExceptionsHandler] SELECT DISTINCT ON expressions must match initial ORDER BY expressions
QueryFailedError: SELECT DISTINCT ON expressions must match initial ORDER BY expressions**
if I add this two order functions at the and, I dont get error but my query not sorting according to timestamp, instead sort only with item_id. Actually I only want to sort according to timestamp. How can I refactor my query to make it working ?
.orderBy(
"activityLogEntry.originalData ::jsonb -> 'source' ->> 'item_id'",
'DESC'
)
.addOrderBy('activityLogEntry.timestamp', 'DESC')

Add new column count in Laravel controller

I am trying to add a new column total_count that contains the count of all rows in sample for pagination.
Is there a way to select count(*) as total_count in $sample itself instead of $total_count = $sample->count()
$var1 = $request->xyz;
$var2 = $request->abc;
$take = $request->take;
$skip = $request->skip;
$sample = DB::table('table_name')
->where('column_name1', $var1)
->where('column_name2', $var2)
->offset($skip)->limit($take)
->get();
$total_count = $sample->count();
$encrypted = AESEncrypt($sample);
return json_encode($encrypted);
OR can I write something like this
$sample = DB::table('table_name')
->select('table_name.*', DB::raw('COUNT(column_name) as total_count'))
->where('column_name1', $var1)
->where('column_name2', $var2)
->offset($skip)->limit($take)
->get();
You directly call
->paginate(10)
at the end of your query like:
$sample = DB::table('table_name')
->where('column_name1', $var1)
->where('column_name2', $var2)
->paginate(10);
Laravel itself handles all count pages etc.
You can use below code for total count of your table. If you need special where case then you should it too.
ModelName::count();
Or you can use
DB::table('table_name')->count();
You can read more in here

How count by the first letters in Laravel Query Builder?

I want to make a count by the first letters... I have this column
I would like to count each OE rows and each GICS rows
I'm working with this query
$data4 = DB::table('incidencias')
->select(DB::raw('grupo_asig as grupo_asig'), DB::raw('count(*) as number'))
->whereNotIn('grupo_asig', [''])
->groupBy('grupo_asig')
->orderBy('number', 'desc')
->get();
Use CASE WHEN and count the field like OE and ASIG
$data4 = DB::table('incidencias')
->select(DB::raw("(CASE WHEN grupo_asig LIKE 'OE%' THEN 'OE'
WHEN grupo_asig LIKE 'GICS%' THEN 'GICS'
END) AS grupo_asig_type"),
DB::raw('COUNT(*) as number'))
->whereNotIn('grupo_asig', [''])
->groupBy('grupo_asig_type')
->orderBy('number', 'desc')
->get();
You should try to use the [LIKE][1] function then and add it to your query:
->where('grupo_asig', 'like', 'OE%')
->where('grupo_asig', 'like', 'GICS%')
Edit:
I tried a lot around and came to this solution and made a SQL fiddle: http://sqlfiddle.com/#!9/06a39b/8
Does it help you?
You could use Collections. No real need to change your query much.
$data4 = DB::table('incidencias')
->select('grupo_asig')
->selectRaw('count(*) as number'))
->whereNotIn('grupo_asig', [''])
->groupBy('grupo_asig')
// ->orderBy('number', 'desc') Unless you use this array somewhere, it's not needed.
->get();
use Illuminate\Support\Str;
...
// php >= 7.4.0
$oe_count = $data4->filter(fn($data) => Str::startsWith($data->grupo, 'OE '))->count();
$gigs_count = $data4->filter(fn($data) => Str::startsWith($data->grupo, 'GIGS '))->count();
// php < 7.4.0
$oe_count = $data4->filter(function ($data) {
return Str::startsWith($data->grupo, 'OE ');
})->count();
$gigs_count = $data4->filter(function ($data) {
return Str::startsWith($data->grupo, 'GIGS ');
})->count();
Starting with Laravel 6, you can also use cursor() instead of get() in your query to return a LazyCollection. It's faster for this scenario.
I would suggest using a query for that:
refer to this answer
SELECT
LEFT(grupo_asig, 1) AS first_letter,
COUNT(*) AS total
FROM incidencias
GROUP BY first_letter

Laravel/SQL: where column Equals NOT and NULL

LARAVEL 5.4 (but probably it's a more general SQL question)
Hello! I have a table with a structure:
Suppose it's my model 'Table'.
I want a query which:
uses (receives) variables :
$id of array ['id', 'string', integer]
where string is '<' or '>'
$status_not_bad = bool;
(if true - include all rows where 'status' !== 'bad' AND 'status' IS NULL);
for example, we are given:
$id = [['id', '>', 0]];
$status_not_bad = true;
Table::thisquery() ... ->get();
"get rows where status is not bad and id > 0" returns rows 1 and 3.
but if we given:
$id = [['id', '<', 3]];
$status_not_bad = true;
Table::thisquery() ... ->get();
"get rows where status is not bad and id < 3" returns row 1
(it should be same query which return those results using those variables).
Probably you end with something like this:
if ($status_not_bad) {
$nStatus = 'bad';
} else {
$nStatus = 'good';
}
Table::thisquery()->where('status', '<>', $nStatus)
->whereNotNull('status')
->where($id[0], $id[1], $id[2])
->get();
But it would be a good idea to check $id keys first.
Since row id = 3 you need <= in your where statement to have that row included in the result set
$id = ['id', '<=', 3];
So, I this works:
$chain = Sample::when($status_not_bad, function($query){
return $query->where('status', '<>', 'bad')
->orwhereNull('status');
})
->where([$id])
->get();

Laravel 5 Eloquent where and or in Clauses

i try to get results from table with multiple where and/or clauses.
My SQL statement is:
SELECT * FROM tbl
WHERE m__Id = 46
AND
t_Id = 2
AND
(Cab = 2 OR Cab = 4)
How i can get this with Laravel Eloquent?
My Code in Laravel is:
$BType = CabRes::where('m_Id', '=', '46')
->where('t_Id', '=', '2')
->where('Cab', '2')
->orWhere('Cab', '=', '4')
->get();
Using advanced wheres:
CabRes::where('m__Id', 46)
->where('t_Id', 2)
->where(function($q) {
$q->where('Cab', 2)
->orWhere('Cab', 4);
})
->get();
Or, even better, using whereIn():
CabRes::where('m__Id', 46)
->where('t_Id', 2)
->whereIn('Cab', $cabIds)
->get();
Also, if you have a variable,
CabRes::where('m_Id', 46)
->where('t_Id', 2)
->where(function($q) use ($variable){
$q->where('Cab', 2)
->orWhere('Cab', $variable);
})
->get();
When we use multiple and (where) condition with last (where + or where) the where condition fails most of the time. for that we can use the nested where function with parameters passing in that.
$feedsql = DB::table('feeds as t1')
->leftjoin('groups as t2', 't1.groups_id', '=', 't2.id')
->where('t2.status', 1)
->whereRaw("t1.published_on <= NOW()")
>whereIn('t1.groupid', $group_ids)
->where(function($q)use ($userid) {
$q->where('t2.contact_users_id', $userid)
->orWhere('t1.users_id', $userid);
})
->orderBy('t1.published_on', 'desc')->get();
The above query validate all where condition then finally checks
where t2.status=1 and
(where t2.contact_users_id='$userid' or where t1.users_id='$userid')