Laravel query builder doesn't bind values - laravel

I am using laravel query builder like this.
$col1 = Input::get('col1','');
$col2 = Input::get('col2','');
$result = DB::table('table1')
->select('id', 'col1', 'col2', 'col3')
->whereRaw("col1 like '%?%'", [$col1])
->whereRaw("col2 like '%?%'", [$col2])
->orderBy($orderBy, $orderType) //orderBy=col1, ordeyType=ASC
->skip($ofset)->take($limit) //$ofser=0, $limit=10
->get();
I am getting nothing. If I use toSql() function. I am getting this SQL like this
select `id`, `col1`, `col2`, `col3`
from `table1` where col1 like '%?%' and col2 like '%?%'
order by `col1` ASC limit 10 offset 0
The question marks shouldn't be there. It must replace them with the values. I used this code to debug it.
Log::info(var_export(DB::getQueryLog(), true));
The Logs look like this
2 =>
array (
'query' => 'select `id`, `col1`, `col2`, `col3` from `table1` where col1 like \'%?%\' and col2 like \'%?%\' order by `col1` ASC limit 10 offset 0',
'bindings' =>
array (
0 => 'k',
1 => '',
),
'time' => 25.71,
I think bindings doesn't work pr I'm doing something wrong. Because If I try this code in database It works. (In Addition, I want to get the actual sql that send to the database. How do I do that?)
select `id`, `col1`, `col2`, `col3` from `table1`
where col1 like '%k%' and col2 like '%%'
order by `col1` ASC limit 10 offset 0

Figured it out. The ? needs to go by itself, so concatenate the % symbols to your col variables. And put your col variables in an array (assuming you're using Laravel 4)
Change:
->whereRaw("col1 like '%?%'", [$col1])
->whereRaw("col2 like '%?%'", [$col2])
To:
->whereRaw("col1 like ?", array('%'.$col1.'%'))
->whereRaw("col2 like ?", array('%'.$col2.'%'))

try
->whereRaw("col1 like '%?%'", [$col1])
->whereRaw("col2 like '%?%'", [$col2])
to
->whereRaw("col1 like '%?%'", $col1)
->whereRaw("col2 like '%?%'", $col2)

Related

how convert sql to Laravel

I am new to laravel, I am having trouble converting my sql to Laravel Query.
Example
INSERT INTO table(field1, field2) SELECT 'value1', 'value2' WHERE NOT EXISTS(SELECT 1 FROM tabla WHERE campo = 'search');
this is my code
INSERT INTO siryus.presupuesto_anio (id, fk_agencia_id, anyo, estado, created_at, updated_at) SELECT 30,4,2020, 'A', '2021-04-21 10:35:01','2021-04-21 10:35:01' WHERE NOT EXISTS(SELECT 1 FROM presupuesto_anio WHERE fk_agencia_id = '4');
i want insert only if there is no field with that value. The insert is done only if there are values ​​of the select, and the select will return data only if the WHERE is met.
Inside the WHERE we have a simple SELECT that verifies if the data exists in the table.
I want to convert it to example code
DB::table('presupuesto_anio') ->join('agencia','presupuesto_anio.fk_agencia_id','agencia.id') ->select('presupuesto_anio.*','agencia.descripcion') ->get();
im not understand with your questions, maybe this will help:
$check = Model::where('id', 4)->first();
if(!$check){
Model::create({
'column1' => 'value1',
'column2' => 'value2'
});
}

cake php distinct date_format

Please I need some help with cakephp3 mysql distinct.
My desire result in SQL:
select distinct(date_format(torokuDate,'%Y')) as year
from kani_tbl
where torokuDate >= '2000-01-01'
order by torokuDate ASC
limit 1;
But I get the wrong result:
SELECT (date_format((torokuDate), '%Y')) AS `year`
FROM kani_tbl
WHERE torokuDate > :c0
GROUP BY torokuDate
ORDER BY torokuDate ASC
LIMIT 1
My model src:
$query = $this->find();
$time = $query->func()->date_format([
'torokuDate' => 'identifier',
"'%Y'" => 'literal'
]);
$yearList = $query->select(['year' => $time])
->distinct('torokuDate')
->from('kani_tbl ')
->order(['torokuDate' => 'ASC'])
->where(['torokuDate >' => '2000-01-01'])
->limit(1);
// ->hydrate(false)
// ->toArray();
var_dump($yearList);
Please help me to add distinct field in the MySQL command.
As your expected query, you need to distinct result of date_format(torokuDate, '%Y'), not the 'torokuDate' field. So your code should be like this:
$yearList = $query->select(['year' => $time])
->distinct()
->from('kani_tbl ')
->order(['torokuDate' => 'ASC'])
->where(['torokuDate >' => '2000-01-01'])
->limit(1);
How to use distinct method: https://api.cakephp.org/3.4/class-Cake.Database.Query.html#_distinct

How to use like clause in code iginiter query() WITH BIND PARAMS?

How to use like clause in code iginiter query() WITH BIND PARAMS?
Eg:
When I use
$query = 'SELECT mycol FROM mytable WHERE name LIKE %?';
$name = 'foo';
$db->this->query($query,array($name));
//the clause generated
//SELECT mycol FROM mytable WHERE id LIKE '%'foo'%'
//I expected this
//SELECT mycol FROM mytable WHERE id LIKE '%foo'
I don't to put param values inside query and use like below:
$query = 'SELECT mycol FROM mytable WHERE name LIKE '%foo';
Also I can not use $this->db->like() function as my query consists of:
INSERT IGNORE
and
INSERT INTO table SELECT col FROM table2;
Please suggests?
Thanks,
just use CodeIgniter Query Builder
$name = 'foo';
$query = $this
->db
->select('mycol')
->like('name', $name)
->get('mytable');
$query = 'SELECT mycol FROM mytable WHERE name LIKE ?';
$name = '%foo';
$this->db->query($query,array($name));
codeigniter will replace ? with 'params' value.
if you write this
$query = 'SELECT mycol FROM mytable WHERE name LIKE %?';
$name = 'foo';
//$db->this->query($query,array($name)); //you wrote this line wrong.
//it should be like this
$this->db->query($query,array($name));
it will produce
SELECT mycol FROM mytable WHERE name LIKE %'foo' //inverse comma after % ,actually before and after foo.
So your right way will be
$query = 'SELECT mycol FROM mytable WHERE name LIKE ?';
$name = '%foo';
$this->db->query($query,array($name));
It will produce
SELECT mycol FROM mytable WHERE name LIKE '%foo'
NOTE
You wrote this which is wrong
$db->this->query($query,array($name));
Right way
$this->db->query($query,array($name));

Re-writing Query

Overall Task :- I need to retrieve data from 45 fields in system A and dump that data into a temp table which is then picked up by a unix process which produces an xml data file to be imported into system B.
Specific Question : What would be the best way of retrieving the data to be written into the 45 fields. Majority of the data is independent and can't be retrieved using a single statement. The way i currently retrieve this data is as follows (example below)
My temp tables hold the affected properties ID that i need to extract data for. i.e PROP_LIST_TEMP and ASSOC_PROP_TEMP.
SELECT SUBSTR (pro.pro_propref, 1, 25) UPRN,
(SELECT SUBSTR (adr_building, 1, 100)
FROM addresses, address_usages
WHERE aus_adr_refno = adr_refno
AND aus_aut_far_code = 'PHYSICAL'
AND aus_aut_fao_code = 'PRO'
AND (aus_end_date IS NULL OR aus_end_date > SYSDATE)
AND aus_pro_refno = pro.pro_refno)
BUILDING_NAME,
(SELECT CASE
WHEN (adr_street_number like 'BLOC%'
OR adr_street_number like '%-%'
OR adr_street_number like '%/%')
THEN NULL
ELSE regexp_replace (adr_street_number, '[^[:digit:]]+')
END
FROM addresses, address_usages
WHERE aus_adr_refno = adr_refno
AND aus_aut_far_code = 'PHYSICAL'
AND aus_aut_fao_code = 'PRO'
AND (aus_end_date IS NULL OR aus_end_date > SYSDATE)
AND aus_pro_refno = pro.pro_refno)
STREET_NUMBER,
(SELECT CASE
WHEN (adr_street_number like 'BLOC%'
OR adr_street_number like '%-%'
OR adr_street_number like '%/%')
THEN SUBSTR (adr_street_number, 1, 20)
ELSE REGEXP_REPLACE (adr_street_number, '[^[:alpha:]]+', '')
END
FROM addresses, address_usages
WHERE aus_adr_refno = adr_refno
AND aus_aut_far_code = 'PHYSICAL'
AND aus_aut_fao_code = 'PRO'
AND (aus_end_date IS NULL OR aus_end_date > SYSDATE)
AND aus_pro_refno = pro.pro_refno)
STREET_NUMBER_SUFFIX,
(SELECT SUBSTR (ptv_pty_code, 1, 3)
FROM prop_type_values
WHERE ptv_refno = pro.pro_hou_ptv_refno)
HOUSE_TYPE
FROM properties pro
WHERE pro_refno IN (select * from PIMSS_PROP_LIST_TEMP
UNION
select * from PIMSS_ASSOC_PROP_TEMP)
AND pro.pro_hou_hrv_hot_code IN
(SELECT frv_code
FROM first_ref_values
WHERE frv_frd_domain IN ('ASS_OWN_REF')
AND frv_current_ind = 'Y');
Since the where clauses of the subqueries in the select statement are identical, you could simply pull that out into the where clause, like so:
SELECT SUBSTR (pro.pro_propref, 1, 25) UPRN,
SUBSTR (addr.adr_building, 1, 100) BUILDING_NAME,
CASE WHEN (addr.adr_street_number like 'BLOC%'
OR addr.adr_street_number like '%-%'
OR addr.adr_street_number like '%/%')
THEN NULL
ELSE regexp_replace (addr.adr_street_number, '[^[:digit:]]+')
END STREET_NUMBER,
CASE WHEN (addr.adr_street_number like 'BLOC%'
OR addr.adr_street_number like '%-%'
OR addr.adr_street_number like '%/%')
THEN SUBSTR (addr.adr_street_number, 1, 20)
ELSE REGEXP_REPLACE (addr.adr_street_number, '[^[:alpha:]]+', '')
END STREET_NUMBER_SUFFIX,
(SELECT SUBSTR (ptv_pty_code, 1, 3)
FROM prop_type_values
WHERE ptv_refno = pro.pro_hou_ptv_refno) HOUSE_TYPE
FROM properties pro,
(select adr_building,
adr_street_number
FROM addresses, address_usages
WHERE aus_adr_refno = adr_refno
AND aus_aut_far_code = 'PHYSICAL'
AND aus_aut_fao_code = 'PRO'
AND (aus_end_date IS NULL OR aus_end_date > SYSDATE)) addr
WHERE pro.pro_refno = aus_pro_refno
and pro_refno IN (select * from PIMSS_PROP_LIST_TEMP
UNION
select * from PIMSS_ASSOC_PROP_TEMP)
AND pro.pro_hou_hrv_hot_code IN (SELECT frv_code
FROM first_ref_values
WHERE frv_frd_domain IN ('ASS_OWN_REF')
AND frv_current_ind = 'Y');
You might possibly need an outer join if there's a chance that no rows could be returned from the addr subquery.

Aggregate queries in Laravel Query Builder with group by

I have a table birds.
I want to count each kind of birds in a single query.
I want to combine these queries into a single query in Eloquent if possible.
select count(id) as count1 from birds where kind = a;
select count(id) as count2 from birds where kind = b;
select count(id) as count2 from birds where kind = c;
I tried something like
$first = DB::table('birds')->selectRaw('count(id) as count1')->where('kind','a');
DB::table('birds')->selectRaw('count(id) as count2')->where('kind','b')->unionAll($first)->get();
i don't think union is giving me what i want.
i just need something like
DB::raw(' (select count(id) from birds where kind = a) as count1 ', ' (select count(id) from birds where kind = a) as count2 ', ' (select count(id) from birds where kind = a) as count3 ')
i want to combine the queries
like
Select ( select count(id) from birds where kind = 'a') as count1, ( select count(id) from birds where kind = 'b') as count2, ( select count(id) from birds where kind ='c') as count3 from birds ;
. please give me a tip how to achieve it.
Learn SQL, group by and aggregates in particular.
This is what you need in Laravel:
DB::table('birds')
->selectRaw('count(id) as count, kind')
->groupBy('kind')
->lists('count', 'kind');
// or get()
lists will return an array like below:
array(
'kind_1' => '15',
'kind_2' => '10',
...
);
get would return an array of stdObjects so probably not what you would like:
array(
0 => StdObject {
'kind' => 'kind_1',
'count' => '15'
},
1 => StdObject {
'kind' => 'kind_2',
'count' => '10'
},
...
);
If you want to get only particular kinds of birds, then use whereIn:
DB::table('birds')
->selectRaw('count(id) as count, kind')
->groupBy('kind')
->whereIn('kind', ['kind_1', 'kind_2', 'kind_3'])
->lists('count', 'kind');

Resources