How can I generate the SQL query using SQL::Abstract? - sql

How do I generate the WHERE clause for this query using SQL::Abstract:
SELECT COUNT(*) FROM table WHERE id =
111 AND NOT FIND_IN_SET(type,
'1,2,3,4') AND status = 'pending';
What's the proper way to include conditions like WHERE FIND_IN_SET(type, '1,2,3,4')?

See the not_bool unary operator option:
use SQL::Abstract;
my $sql = SQL::Abstract->new;
my $where = {
id => 111,
status => 'pending',
-not_bool => "FIND_IN_SET(type, '1,2,3,4')",
};
my ($query, #bind) = $sql->select(
'table',
'count(*)',
$where,
);
This is how $query looks:
SELECT count(*) FROM table WHERE ( ( (NOT FIND_IN_SET(type, '1,2,3,4'))
AND id = ? AND status = ? ) )

This code generates the WHERE clause:
my $sql = SQL::Abstract->new;
my %where = (
id => 111,
-nest => \"NOT FIND_IN_SET(type, '1,2,3,4')",
status => 'pending',
);
my ($stmt, #bind) = $sql->where(\%where, \#order);

FIND_IN_SET isn't standard SQL, so SQL::Abstract doesn't have support for it. You can however put any literal SQL into an SQL::Abstract query. I expect your solution lies down that route.

Take a look at: DALMP
Database Abstraction Layer for MySQL using PHP
0% fat and extremely easy to use. Only connect to database when needed.
http://code.google.com/p/dalmp/

Related

Yii2: how to use subquery with ActiveRecord?

I want to create a find function to use then in a GridView widget My I don't know how to use a subquery.
This is the simple version of the PostgreSQL query that I have:
SELECT color
FROM cars
LEFT JOIN (
SELECT name
FROM companies
)
Here is what I a trying and doesn't work:
$query = Cars::find()
->select([
'color' => '
SELECT name // Problem here.
FROM companies // Problem here.
',
]);
Your expected query is not what you are trying to do. You can add a custom subquery as
$query = Cars::find()
->select([
'(SELECT name FROM companies) AS xxx'
]);
But if you want to add a field from joined table to the grid, then you should have a relation defined and then you can easily add such a column to your grid. See https://www.yiiframework.com/doc/guide/2.0/en/db-active-record#relational-data
You can use instance of ActiveQuery in leftJoin() method like this:
$subQuery = Companies::find()
->select('name', 'id'); //I've added ID to show how to write on condition
$query = Cars::find()
->select('color')
->leftJoin(
['alias' => $subQuery],
'alias.id = cars.company_id'
);
See documentation for more details about leftJoin() and join() methods.
$query = Cars::find()
->select(['cars.color','companies.name'])
->leftJoin('companies', 'cars.company_id = companies.id');

Translate this Linq into SQL

I have this linq code that I need to translate into identical SQL so I can query the database directly... I get stuck when it gets complicated. Can anyone help?
Linq
_db.BatchPaymentSplits
.Where(bps => bps.YearSetupId == i.YearSetupId)
.Where(bps => bps.CustomerIdEntered != null)
.Where(bps => _db.BatchPayments
.Where(bp => _db.Batches.Where(b => b.BatchTypeId.Equals("T"))
.Select(b => b.BatchId)
.Contains(bp.BatchId)
)
.Select(bp => bp.BatchPaymentId).Contains(bps.BatchPaymentId)
)
SQL so far
SELECT * FROM BatchPaymentSplit
WHERE YearSetupId = 1
AND CustomerIdEntered IS NOT NULL
I can't say that I think the LINQ or the resulting SQL is the best way to express this query (should be using Join I think), but this is my literal translation:
SELECT *
FROM BatchPaymentSplits bps
WHERE bps.YearSetupId = i.YearSetupId AND
bps.CustomerIdEntered IS NOT NULL AND
EXISTS (SELECT * FROM BatchPayments bp
WHERE EXISTS (SELECT * FROM Batches b
WHERE b.BatchTypeId = 'T' AND
b.BatchId = bp.BatchId) AND
bp.BatchPaymentId = bps.BatchPaymentId)
You can translate Contains when applied to an IEnumerable/IQueryable as an EXISTS query with an = expression.

How can I do this SQL in Query builder laravel

How can I do this SQL in Query builder laravel
select Doctor_id from doctors where Doctor_id NOT IN
(SELECT Doctor_id from report_reviewers WHERE Report_id = 26 )
Try with this
$result = DB::table('doctors')
->whereNotIn('doctor_id', function($q){
$q->from('report_reviewers')
->select('Doctor_id')
->where('Report_id', '=', 26)
})
->select('doctor_id')
->get();
Whenver in doubt, if you know the raw SQL, you can simply do
$query = 'select Doctor_id from doctors ...';
$result = DB::select($query);
Also, all credit goes to this genius How to create a subquery using Laravel Eloquent?
Update
The missing argument comes from the closure you are using
->whereNotIn('doctor_id', function($q,$id){
$q->from('report_reviewers')
->select('Doctor_id')
->where('Report_id',$id);
})
You need to pass the $id variable like this
->whereNotIn('doctor_id', function($q) use ($id) {
$q->from('report_reviewers')
->select('Doctor_id')
->where('Report_id',$id);
})
Try again and see.

What does it mean "?" in sql query?

I just got a query cod :
SELECT o.id,o.sort_order,od.object FROM i_objects o, i_objects_description od
WHERE o.id=od.objects_id AND o.object_status = ? AND od.languages_id = ?
ORDER BY o.sort_order ASC
I want figure it out what does "?" mean in this query ?
If I run this query , it gives me this error :
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 '?
Im using PEAR and this is my function :
function getArrayObjects( $language_id )
{
$q = 'SELECT o.id,o.sort_order,od.object FROM ' . TABLE_OBJECTS . ' o, ' . TABLE_OBJECTS_DESCRIPTION . ' od ';
$q.= 'WHERE o.id=od.objects_id AND o.object_status = ? AND od.languages_id = ? ';
$q.= 'ORDER BY o.sort_order ASC';
$sth = $this->_db->prepare( $q );
$res = $sth->execute( array( 'active', $language_id ) );
//var_dump($res);echo "<br>";echo "<br>";echo "<br>";
$objects = array();
while( $row = $res->fetchRow())
{
$objects[$row['id']] = $row;
}
return $objects;
}
It's a placeholder for parameter. In your query you have this:
AND o.object_status = ? AND od.languages_id = ?
And then you execute it like this:
$res = $sth->execute( array( 'active', $language_id ) );
So, when query is actually executed by database server, object_status is 'active' and language_id is $language_id.
This is done this way to guard from SQL injection. Another reason is efficiency. When you use prepared statements, database doesn't need to parse/compile query each time. It uses the template and just substitutes values in it. (more on this: Prepared statement)
The ? are placeholder the values of which are filled in in the $sth->execute( array( 'active', $language_id ) ) statement.
One of the main purposes for this construct is to prevent sql injection attacks.
Its a Used to set the value dynamically ,in other words place holder
These are "parametrized queries". While evaluating "?" are replaced with given values (it's called binding). They protect from sql injection and makes possible to optimize queries.

join with AND id=1 with SQL::Abstract::More

I'm trying to do a join using SQL::Abstract::More that has an `and and then a literal value, not on a table column.
=>{table.table_id=table_id,table_log.date>table.date,table_log.event_id=1}
gd_audit_log
the resulting output that I want
LEFT OUTER JOIN table_log ON (
table_log.date > table.date
AND table.table_id = table_log.table_id
AND table_log.event_id = 1
)
this code works except for
AND table_log.event_id = 1
the error is
... failed: Unknown column 'table_log.1' in 'on clause'
obviously it's generating the wrong SQL, what I'm trying to figure out is how to get it to generate the SQL I need.
From RT Bug 84972. To insert a literal value, you need to use the hashref syntax, instead
of the string syntax :
my $result = $sqla->join(
'table',
{ operator => '=>',
condition => { '%1$s.table_id' => {-ident => '%2$s.table_id'},
'%2$s.date' => {'>' => {-ident => '%1$s.date'}},
'%2$s.event_id' => 1}},
'table_log'
);
Seems to me that table_log.event_id = 1 isn't a valid join clause, but should be in a where clause.
Use force Luke
qw/table
=>{table.table_id=table_id,table_log.date>table.date,table_log.event_id='1'}
table_log/
need 'escape' 1 by single quote