Laravel get just updated rows in date range - using WhereBetween and Where in query - laravel

I have jobs table in the database with the default columns created_at and updated_at.
I want to return the number of jobs created and the number updated.
However as the updated_at column is populated at the point of creation, I want to exclude any jobs where the updated_at value is the same as the created_at value (in order to get just the jobs that have been updated since being created).
I use the following code to get the number of updated jobs between a time range.
$jobsUpdated = Job::where('id', $id)
->whereBetween('updated_at', [$value['fromDate'], $value['tillDate']])
->count();
How can I add another where clause to exclude those results which have the same value as created_at.
In theory something like:
->andWhere('updated_at', '!=' , 'created_at')
But andWhere does not exist, so this is just to show my thinking.
Thanks!

$jobsUpdated = Job::where('id', $id)
->whereBetween('updated_at', [$value['fromDate'], $value['tillDate']])
->whereColumn('updated_at', '!=' , 'created_at')
->count();
to compare column value use whereColumn() function referenced by official doc

Related

How to query multiple where in laravel

I have a query that gets all the message between two id (user_id and to_user_id). I want to select all the query all the message of user in the two tables.
I have already made two where and it doesn't seem to work. It is just returning null.
$last_message = DB::table('messages')
->select('content')
->where('user_id','=',Auth::user()->id)
->where('to_user_id','=',Auth::user()->id)
->orderBy('updated_at', 'desc')
->first();
I expect the output of all the message of user
You should check on this Auth::user()->id,
to see if it has a value or not. Also check on the datatype between table field and data source in query builder.

How to Get Last Updated Record with Laravel Query Builder?

I'm using Laravel Query Builder to get the last updated record from the database. However, it displays a different id with a different update_date. The update_date is correct, and it shows me last updated_date, but every time I'm getting the first id.
$results = DB::table('customer_info as cust_info')
->join('client_emp as client_info', 'cust_info.id', '=', 'client_info.cust_id')
->select('cust_info.id', DB::raw('MAX(cust_info.updated_at)'))
->orderBy('cust_info.id','DESC')
->first();
In the above query, I write select to get the id of last updated record.
->select('cust_info.id', DB::raw('MAX(cust_info.updated_at)'))
However, it shows me the last updated_date only with the first id from the table every time.
Try this:
orderBy('updated_at','DESC')->first()->id
Here you are getting the id of the latest updated record. When you remove the first() method, you will get the whole collection sorted by 'updated_at'

In Laravel Eloquent, how do I reference primary query in subquery

I have a model User that has many Orders. Orders have many products, with the pivot table order-product. I don't want to preload and iterate through the orders if at all possible.
I need to return users where
signed_date === true on User
order_date on Order is after signed_date on User
order-product shows product hasn't been paid
I am failing on number 2.
In the following code, the first query within whereHas is wrong. I don't know how to reference the signed date of the user from within the where has. If I was iterating through users in a collection I could do something like ($query) use $user, but how do I do this without preloading all the users?
return User::whereNotNull('signed_date')
->whereHas('orders', function ($query) {
$query->where('order_date', '<=', 'user.signed_date');
$query->whereHas('products', function ($q) {
$q->where('paid', false);
});
})
->get(['id','fname','lname', 'title', 'signed_date']);
I would like to use eloquent if possible. If that is not possible, I would be happy for tips in solving this problem using the query builder/sql.
The Eloquent query builder has a special function called whereColumn('a', '<=', 'b') to compare columns instead of a column against a value. Using this function instead of a normal where() is necessary because of the way the query builder builds the actual query. You need to let the query builder know that you are going to pass a column name instead of a value for proper escaping and formatting of the query string.
Anyway, it seems you can also pass column names prefixed with a table name to the function, allowing you to compare columns across tables:
$query->whereColumn('orders.order_date', '<=', 'users.signed_date')
This works because you are using whereHas() in your query. Your query basically gets translated to:
SELECT id, fname, lname, title, signed_date
FROM users
WHERE signed_date NOT NULL
AND EXISTS (
SELECT 1
FROM orders
WHERE orders.order_date <= users.signed_date
AND EXISTS (
SELECT 1
FROM products
WHERE paid = 0
)
)
It might actually be not necessary at all to use the table name together with the column name in whereColumn(). But in case you'll ever add a column named the same on another table, the query might break - so IMHO it is good practice to use the table name in custom queries.
By the way, the reason this will not work together with with('relationship') is that this function results in an additional query and you obviously cannot compare columns across queries. Imagine the following:
Order::with('user')->take(5)->get();
It will be translated into the following:
SELECT *
FROM orders
LIMIT 5
SELECT *
FROM users
WHERE id IN (?, ?, ?, ?, ?)
where the five ? will be the user_ids of the orders. If the first query returns multiple rows with the same user_id, the amount of rows fetched from the users table gets reduced of course.
Note: All the queries are only examples. Might be that the query builder builds different queries based on the database type and/or escapes them differently (i.e. column names in backticks).

Laravel join two tables with where that compares two date time columns

I have two tables that I want to run joint query on using the value of two date time columns, I have products table and sync_status tables, I want to return all products with updated_at date time greater than synced_at date time.
DB::table('products')
->join('sync_statuses', function ($join) {
$join->on('products.product_number', '=', 'sync_statuses.product_number')
->where('products.updated_at', '>', 'sync_statuses.synced_at')
->whereNull('products.deleted_at');
})
->select('products.product_number');
This SQL represents what I am trying to achieve using Eloquent:
SELECT products.product_number
FROM products
JOIN push_statuses
ON products.product_number = statuses.product_number
AND (
statuses.synced_at IS NULL
OR products.updated_at > statuses.synced_at
)
You have to use on() instead of where() to compare columns:
->on('products.updated_at', '>', 'sync_statuses.synced_at')
This worked for me:
DB::table('products')
->join('statuses', function ($join) {
$join->on('products.product_number', '=', 'statuses.product_number')
->where(DB::raw('products.updated_at'), '>=', DB::raw('statuses.synced_at'))
->whereNull('products.deleted_at');
})->select('products.product_number');
I needed to use DB::raw('products.updated_at') to reference each date time column in the where() clause.

laravel - Updating row changes created_at column

When I update my row with the query below, it changes not only the updated_at column for the row, but also the created_at column. Why? How can I prevent this so that it only changes the updated_at column
Post::where('id', Input::get('post_id'))
->where('user_id', getUserID())
->update(array('message' => Input::get('message')));
From Laravel documentation at
Insert-update-delete
You can use following method to perform update
$x = Post::find(Input::get('post_id')); // may need to use intval()
$x->message = Input::get('message');
$x->save();
This should update the record with only updating 'updated_at' timestamp.

Resources