Laravel/SQL: return rows where column Equals NOT 'something" and NULL - sql

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).

I've never used laravel before so my syntax could be off, but I know you want to use MySQL's ifNull function for this:
Table::where([['id', '>', 0], ['number', '>', 2])->whereRaw("IfNull(status, 'blah') <> 'bad'")->get();

Just chain your ->where() clauses. Maybe also consider wrapping them to prevent conflicting with any additional:
$results = Table::where("id", ">" 0)
->orWhere("number", ">", 2)
->orWhereNull("status")
->get();
Or, wrapped:
$results = Table::where(function($query){
$query->where("id", ">" 0)
->orWhere("number", ">", 2)
->orWhereNull("status");
})->get();
If you want to see what the actual query you're executing is, replace ->get() with ->toSql(), and use dd($result);:
$results = Table::where(...)->toSql();
dd($results);
Edit: Sounds like we need multiple wrapping queries, due to multiple conditions:
$results = Table::where(function($query){
$query->where("status", "!=", "bad")
->where("id", "<", 3); -- "status is not bad and id < 3"
})->orWhere(function($query){
$query->where("status", "!=", "bad")
->where("id", ">", 0); -- "status is not bad and id > 0"
})->get();
That should handle paired conditions as noted in your comment.

Related

Can Laravel automatically switch between column = ? and column IS NULL depending on value?

When building a complex SQL query for Laravel, using ? as placeholders for parameters is great. However when the value is null, the SQL syntax needs to be changed from = ? to IS NULL. Plus, since the number of parameters is one less, I need to pass a different array.
To get it to work, I have written it like this, but there must be a better way:
if ($cohortId === null) {
// sql should be: column IS NULL
$sqlCohortString = "IS NULL";
$params = [
Carbon::today()->subDays(90),
// no cohort id here
];
} else {
// sql should be: column = ?
$sqlCohortString = "= ?";
$params = [
Carbon::today()->subDays(90),
$cohortId
];
}
$query = "SELECT items.`name`,
snapshots.`value`,
snapshots.`taken_at`,
FROM snapshots
INNER JOIN (
SELECT MAX(id) AS id, item_id
FROM snapshots
WHERE `taken_at` > ?
AND snapshots.`cohort_id` $sqlCohortString
GROUP BY item_id
) latest
ON latest.`id` = snapshots.`id`
INNER JOIN items
ON items.`id` = snapshots.`item_id`
ORDER by media_items.`slug` ASC
";
$chartData = DB::select($query, $params);
My question is: does Laravel have a way to detect null values and replace ? more intelligently?
PS: The SQL is for a chart, so I need the single highest snapshot value for each item.
You can use ->when to create a conditional where clause:
$data = DB::table('table')
->when($cohortId === null, function ($query) {
return $query->whereNull('cohort_id');
}, function ($query) use ($cohortId) {
// the "use" keyword provides access to "outer" variables
return $query->where('cohort_id', '=', $cohortId);
})
->where('taken_at', '>', $someDate)
->toSql();

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')

Drupal - Query to count all nodes of content_type "A" in which field_b is "X"

I need to make a query for a drupal site. Initially I just needed to COUNT the number of nodes for a content type:
$query = "SELECT COUNT(*) amount FROM {node} n WHERE n.type ='A'";
$result = db_query($query)->fetch();
return $result->amount;
Now I need that but only for nodes that have the field_b equal to 'X'. How can I do this?
I tried EntityFieldQuery without sucess:
$query = new EntityFieldQuery;
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'A')
->fieldCondition('field_b', 'value', 'X');
$results = $query->execute();
return $results->amount;
Any help?
You can set the query to be a count query only by using :
$count = $query->count()->execute();

how to use like query in drupal

How to write SQL LIKE Query in drupal ,
SELECT title FROM { node } WHERE type='%s'
i want to add the LIKE CONDITION IN THAT
SELECT title FROM { node } WHERE type='%s' AND LIKE '%S%'
i think i writtern wrong like query formnat, can rewrite and tell me,
Just use % to escape.
$result = db_query('SELECT title FROM {node} WHERE type = "%s" AND title LIKE "%%%s%%"', 'type', 'title');
while ($row = db_fetch_object($result)) {
// do stuff with the data
}
Node type does not need escaping.
And here is an example with how to use LIKE in a dynamic query (Drupal 7 Only):
$query = db_select('node', 'n')
->fields('n', array('title'))
->condition('type', 'my_type')
->condition('title', '%' . db_like(search_string) . '%', 'LIKE');
$result = $query->execute()->fetchCol();
db_like() is used to escapes characters that work as wildcard characters in a LIKE pattern.
drupal_query replace %% to % and %s to value string
so your code will be
$sql = "SELECT title FROM node WHERE type='%%%s' AND title LIKE '%%%S%%'";
$type = "type to use in query";
$title = "title to use in query";
$result = db_result(db_query($sql, $type, $title));
OK, so you want the LIKE operator to refer to the title column. Use this query:
$sql = "SELECT title FROM node WHERE type='%s' AND title LIKE '%S%'";
$type = "type to use in query";
$title = "title to use in query";
$result = db_result(db_query($sql, $type, $title));
This is because the LIKE operator requires a column name to be specified. Otherwise, your database doesn't have any idea what value you want to perform the comparison on. See here.