Laravel Elequent Count from Multiple Columns - sql

I'm trying to get the count of 2 columns('published', 'expires') in Laravel 5.6.
I want my results count to only show if the item is published, not expired or there is no expiration date.
my code:
$today = date('Y-m-d');
$numrecords = deals::where('published',1)
->orwhereDate('expires', '=', '')
->orwhereDate('expires', '>=', $today)
->count();
thanks
Nabi

$numrecords = deals::where('published', 1)
->where(function($q){
return $q->whereNull('expires')
->orwhereDate('expires', '>=', Carbon::today());
})
->count();
Above should give you :
SELECT * FROM deals
WHERE
published = 1 AND
( expires IS NULL OR DATE(expires) >= today_date)

Here are the queries you are supposed to write: (today is a Laravel function)
// 1. if the item is published
$item->where('published', true);
// 2. expire date is after today
$item->where('expiry_date', '>', today());
// 3. expire date is null
$item->whereNull('expiry_date');
//4. emit expired items
$item->where('expiry_date', '>', today());
I think some of your check conditions are wrong.
Also, your logic is very messy as well. I am not sure what condition you are trying to write, but do write it down, under what condition, is an item considered into the count, then you decide to use where or orWhere.

Related

Laravel carbon check if past date from table

So i want to get data from my API where datetime in the past,but when i tried this code.. its appear that i got data where ONLY DATE in the past not include the time
$id_merchant = $request->input('id_merchant');
$Promotion = DB::table('promotion')
->leftJoin('product', 'product.id', '=', 'promotion.id_product')
->where('promotion.id_merchant', '=', $id_merchant)
->whereDate('end_time','>=', Carbon::now())
->select('promotion.*','product.product_name','product.price','product.stock')
->get();
i see some people solve it with
$end_time->isPast() function
but i dont know how to implement this in my case.
sorry for my english
->where('end_time', '>=', Carbon::now())
(whereDate filter the time)

Laravel Eloquent with `has` and `where` on dates

I try to get records on relation when there is only one record in the one to many relation and only the records where the start_date is bigger than now() and here is what I'm trying:
$newStarters = User::has('periods', 1)->with(['periods' => function($q) {
$q->where('start_date', '>', Carbon::now()->subWeek(2)->format('Y-m-d') );
}])->get();
in this case the date filter does not applies.
What is the propper way to do this?
Probably you are looking this:
$newStarters = User::whereHas('periods', function($q) {
$q->where('start_date', '>', Carbon::now()->subWeek(2)->format('Y-m-d') );
}, '=', 1)->get();
See Query relationship existence section for more details.

cannot group with eloquent with PostreSQL

Here's my Eloquent query:
$visits = Visit::orderBy('date', 'desc')->groupBy('user_id')->get(['date', 'user_id']);
But posgreSQL is refusing the query, telling me:
SQLSTATE[42803]: Grouping error: 7 ERROR: column "visits.date" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: select "date", "user_id" from "visits" group by...
the same stuff works on MySQL when I disable ONLY_FULLY_GROUP_BY
what can I do to make it work? It would be great if I didn't have to edit configs, just the code.
This selects the latest date for each user_id:
$sub = Visit::select('user_id', DB::raw('max("date") "date"'))->groupBy('user_id');
$sql = '(' . $sub->toSql() . ') as "sub"';
$visits = Visit::join(DB::raw($sql), function($join) {
$join->on('visits.user_id', 'sub.user_id')
->on('visits.date', 'sub.date');
})->orderBy('visits.date', 'desc')->get(['visits.date', 'visits.user_id']);
If there are multiple visits for a user_id and date combination, the query returns all of them. Removing the duplicates is possible, but makes the query more complex.
It's easier to remove them afterwards:
$visits = $visits->unique('user_id');
Using postgre sql you could use distinct on user_id and order your date column to pick latest date per user_id, In laravel you could raw expression
$visits = Visit::select(DB::raw('distinct on (user_id)'), 'date')
->orderBy('date', 'desc')
->get();
Demo

django using .extra() got error `only a single result allowed for a SELECT that is part of an expression`

I'm trying to use .extra() where the query return more than 1 result, like :
'SELECT "books_books"."*" FROM "books_books" WHERE "books_books"."owner_id" = %s' % request.user.id
I got an error : only a single result allowed for a SELECT that is part of an expression
Try it on dev-server using sqlite3. Anybody knows how to fix this? Or my query is wrong?
EDIT:
I'm using django-simple-ratings, my model like this :
class Thread(models.Model):
#
#
ratings = Ratings()
I want to display each Thread's ratings and whether a user already rated it or not. For 2 items, it will hit 6 times, 1 for the actual Thread and 2 for accessing the ratings. The query:
threads = Thread.ratings.order_by_rating().filter(section = section)\
.select_related('creator')\
.prefetch_related('replies')
threads = threads.extra(select = dict(myratings = "SELECT SUM('section_threadrating'.'score') AS 'agg' FROM 'section_threadrating' WHERE 'section_threadrating'.'content_object_id' = 'section_thread'.'id' ",)
Then i can print each Thread's ratings without hitting the db more. For the 2nd query, i add :
#continue from extra
blahblah.extra(select = dict(myratings = '#####code above####',
voter_id = "SELECT 'section_threadrating'.'user_id' FROM 'section_threadrating' WHERE ('section_threadrating'.'content_object_id' = 'section_thread'.'id' AND 'section_threadrating'.'user_id' = '3') "))
Hard-coded the user_id. Then when i use it on template like this :
{% ifequal threads.voter_id user.id %}
#the rest of the code
I got an error : only a single result allowed for a SELECT that is part of an expression
Let me know if it's not clear enough.
The problem is in the query. Generally, when you are writing subqueries, they must return only 1 result. So a subquery like the one voter_id:
select ..., (select sectio_threadrating.user_id from ...) as voter_id from ....
is invalid, because it can return more than one result. If you are sure it will always return one result, you can use the max() or min() aggregation function:
blahblah.extra(select = dict(myratings = '#####code above####',
voter_id = "SELECT max('section_threadrating'.'user_id') FROM 'section_threadrating' WHERE ('section_threadrating'.'content_object_id' = 'section_thread'.'id' AND 'section_threadrating'.'user_id' = '3') "))
This will make the subquery always return 1 result.
Removing that hard-code, what user_id are you expecting to retrieve here? Maybe you just can't reduce to 1 user using only SQL.

SELECT MAX query returns only 1 variable + codeigniter

I use codeigniter and have an issue about SELECT MAX ... I couldnot find any solution at google search...
it looks like it returns only id :/ it's giving error for other columns of table :/
Appreciate helps, thanks!
Model:
function get_default()
{
$this->db->select_max('id');
$query = $this->db->getwhere('gallery', array('cat' => "1"));
if($query->num_rows() > 0) {
return $query->row_array(); //return the row as an associative array
}
}
Controller:
$default_img = $this->blabla_model->get_default();
$data['default_id'] = $default_img['id']; // it returns this
$data['default_name'] = $default_img['gname']; // it gives error for gname although it is at table
To achieve your goal, your desire SQL can look something like:
SELECT *
FROM gallery
WHERE cat = '1'
ORDER BY id
LIMIT 1
And to utilise CodeIgniter database class:
$this->db->select('*');
$this->db->where('cat', '1');
$this->db->order_by('id', 'DESC');
$this->db->limit(1);
$query = $this->db->get('gallery');
That is correct: select_max returns only the value, and no other column. From the specs:
$this->db->select_max('age');
$query = $this->db->get('members');
// Produces: SELECT MAX(age) as age FROM members
You may want to read the value first, and run another query.
For an id, you can also use $id = $this->db->insert_id();
See also: http://www.hostfree.com/user_guide/database/active_record.html#select
CodeIgniter will select * if nothing else is selected. By setting select_max() you are populating the select property and therefore saying you ONLY want that value.
To solve this, just combine select_max() and select():
$this->db->select('somefield, another_field');
$this->db->select_max('age');
or even:
$this->db->select('sometable.*', FALSE);
$this->db->select_max('age');
Should do the trick.
It should be noted that you may of course also utilize your own "custom" sql statements in CodeIgniter, you're not limited to the active record sql functions you've outlined thus far. Another active record function that CodeIgniter provides is $this->db->query(); Which allows you to submit your own SQL queries (including variables) like so:
function foo_bar()
{
$cat = 1;
$limit = 1;
$sql = "
SELECT *
FROM gallery
WHERE cat = $cat
ORDER BY id
LIMIT $limit
";
$data['query'] = $this->db->query($sql);
return $data['query'];
}
Recently I have been utilizing this quite a bit as I've been doing some queries that are difficult (if not annoying or impossible) to pull off with CI's explicit active record functions.
I realize you may know this already, just thought it would help to include for posterity.
2 helpful links are:
http://codeigniter.com/user_guide/database/results.html
http://codeigniter.com/user_guide/database/examples.html