I'm using ZendFramework2 and I need to make a custon query. I tried my query in mysql and it works perfectly.
SELECT p.idProyecto,p.nombre, e.nombre, e.apellido, sum(ar.tiempoEstimado)
estimado,DATE_FORMAT(p.fechaInicio, '%Y/%m/%d') as inicio,
DATE_FORMAT(p.fechaFin, '%Y/%m/%d') as fin, sum(r.tiempoRegistrado) as t_real
FROM Actividad as a
LEFT JOIN ActividadResponsable as ar
ON a.idActividad=ar.idActividad
and a.fechaInicio>="2014-10-13"
and a.fechaFin<="2014-10-19"
LEFT JOIN ActividadPlaneada as ap
On ap.idActividad = ar.idActividad
and ar.idActividad = a.idActividad
LEFT JOIN tipoActividad as ta
on ta.idTipoActividad= ap.idTipoActividad
LEFT JOIN proyecto as p
ON p.idProyecto=a.idProyecto
LEFT JOIN registro as r
ON a.idActividad=r.idActividad
and r.fechaRegistro>="2014-10-13 00:00:00"
and r.fechaRegistro<="2014-10-19 23:59:00"
LEFT JOIN empleado as e
ON p.creador = e.idEmpleado
GROUP BY a.idProyecto;
But when I code this into ZendFramework2 it changes this
LEFT JOIN ActividadResponsable as ar
ON a.idActividad=ar.idActividad
and a.fechaInicio>="2014-10-13"
and a.fechaFin<="2014-10-19"
So the result query that zend generates is
SELECT p.idProyecto, p.nombre, e.nombre, e.apellido, SUM(ar.tiempoEstimado) as estimado, p.fechaInicio as inicio, p.fechaFin as fin, sum(r.tiempoRegistrado) as t_real
FROM `Actividad`
LEFT JOIN `ActividadResponsable` AS `ar` ON `Actividad`.`idActividad`=`ar`.`idActividad`
LEFT JOIN `ActividadPlaneada` AS `ap` ON `ap`.`idActividad` = `ar`.`idActividad` and `ar`.`idActividad` = `Actividad`.`idActividad`
LEFT JOIN `TipoActividad` AS `ta` ON `ta`.`idTipoActividad`= `ap`.`idTipoActividad`
LEFT JOIN `Proyecto` AS `p` ON `p`.`idProyecto`=`Actividad`.`idProyecto`
LEFT JOIN `Registro` AS `r` ON `Actividad`.`idActividad`=`r`.`idActividad`
LEFT JOIN `Empleado` AS `e` ON `p`.`creador` = `e`.`idEmpleado`
WHERE `Actividad`.`fechaInicio` >= :where1 AND `Actividad`.`fechaFin` <= :where2 AND `r`.`fechaRegistro` >= :where3 AND `r`.`fechaRegistro` <= :where4
GROUP BY `Actividad`.`idProyecto`
The php code I have is this
$dbAdapterConfig = array(
'driver' => 'Pdo_Mysql',
'database' => '*',
'username' => '*',
'password' => '*',
'charset' => 'utf8'
);
$dbAdapter = new Adapter($dbAdapterConfig);
$sql = new Sql($dbAdapter);
$query = $sql->select();
$query->from('Actividad');
$query->columns(array(new \Zend\Db\Sql\Expression('p.idProyecto, p.nombre, e.nombre, e.apellido, SUM(ar.tiempoEstimado) as estimado, p.fechaInicio as inicio, p.fechaFin as fin, sum(r.tiempoRegistrado) as t_real')));
$query->join(array('ar' => 'ActividadResponsable'), 'Actividad.idActividad=ar.idActividad', array(), 'left');
$query->where->greaterThanOrEqualTo('Actividad.fechaInicio', $inicio);
$query->where->lessThanOrEqualTo('Actividad.fechaFin', $fin);
$query->join(array('ap' => 'ActividadPlaneada'), 'ap.idActividad = ar.idActividad and ar.idActividad = Actividad.idActividad', array(), 'left');
$query->join(array('ta' => 'TipoActividad'), 'ta.idTipoActividad= ap.idTipoActividad', array(), 'left');
$query->join(array('p' => 'Proyecto'), 'p.idProyecto=Actividad.idProyecto', array(), 'left');
$query->join(array('r' => 'Registro'), 'Actividad.idActividad=r.idActividad', array(), 'left');
$query->where->greaterThanOrEqualTo('r.fechaRegistro', "2014-10-13 00:00:00");
$query->where->lessThanOrEqualTo('r.fechaRegistro', "2014-10-19 23:59:00");
$query->join(array('e' => 'Empleado'), 'p.creador = e.idEmpleado', array(), 'left');
$query->group(array('Actividad.idProyecto'));
$statement = $sql->prepareStatementForSqlObject($query);
$result = $statement->execute();
$records = array();
foreach ($result as $return) {
$records[] = $return;
}
return $result;
the and's in the join query belongs to the joins on statement not the queries where statement , you need to add the on statement as a Expression like this :
$exp = new Expression('Actividad.idActividad=ar.idActividad and a.fechaInicio>=?
and a.fechaFin<=?',array($inicio,$fin));
$query->join(array('ar' => 'ActividadResponsable'), $exp , array(), 'left');
Related
I post an array of skills from the form and i need to fetch list of candidates list related to the elements in array in codeigniter.
Controller
$data = array(
"mode" => $this->input->post("mode"),
"designation" => $this->input->post("designation"),
"notice_period" => $this->input->post("notice_period"),
"skill" => $this->input->post("skills"),
"cities" => $this->input->post("city")
);
$this->load->model("search_model");
$this->load->model("candidate_model");
$data["candidate"] = $this->search_model->fetch_candidate($data);
$data["designation"] = $this->candidate_model->fetch_designation();
$this->load->view('candidate_profiles', $data);
model
function fetch_candidate($data)
{
$mode = $data['mode'];
$designation = $data['designation'];
$notice_period = $data['notice_period'];
$skill = $data['skill'];
$skills = join(",",$skill);
$city = $data['cities'];
$query = $this->db->query("SELECT DISTINCT(U.user_id), U.firstname, U.lastname, U.username, U.usertype, U.email, U.phone, U.address, U.profile_image, C.name AS country,C.id AS countryid, S.name AS state,S.id AS stateid, A.housename, A.street, A.area, A.po, A.city, CJ.designation, CJ.resume, CJ.biography, CJ.hiring_mode, CJ.notice_period, CJ.current_CTC, CJ.expected_CTC, D.designation_id AS desig, D.designation AS desig_name
FROM users AS U
LEFT JOIN address AS A ON U.user_id=A.cand_id
LEFT JOIN cand_job_details AS CJ ON CJ.cand_id=U.user_id
LEFT JOIN designations AS D ON D.designation_id=CJ.designation
LEFT JOIN countries AS C ON C.id=A.country
LEFT JOIN states AS S ON S.id=A.state
LEFT JOIN user_skills AS US ON U.user_id=US.user_id
LEFT JOIN user_interested_cities AS UC ON U.user_id=UC.user_id
WHERE D.designation LIKE '$designation' && (CJ.hiring_mode='2' || CJ.hiring_mode='$mode') && CJ
.notice_period<='$notice_period' && UC.city='$city' && US.skill IN(".implode(",", $skills).")
");
return $query;
}
How to implement this on codeigniter?
Thanks in advance
You need try to add ' around each argument. After it should looks like IN ('PHP','AngularJS'), because it is a string value and datatype is varchar as well.
$skills = "'";
foreach($skill as $item) {
$skills .= $item."',";
}
$skills = trim($skills,",")
Codeigniter comes with a built in Querybuilder - i strongly suggest to use it, because it makes your life much easier, and protects you against SQL injections - which is clearly a problem in your case.
Try the following
function fetch_candidate($data)
{
$this->db
->select('SELECT DISTINCT(U.user_id), U.firstname, U.lastname, U.username, U.usertype, U.email, U.phone, U.address, U.profile_image, C.name AS country,C.id AS countryid, S.name AS state,S.id AS stateid, A.housename, A.street, A.area, A.po, A.city, CJ.designation, CJ.resume, CJ.biography, CJ.hiring_mode, CJ.notice_period, CJ.current_CTC, CJ.expected_CTC, D.designation_id AS desig, D.designation AS desig_name')
->from('users U')
->join('address A', 'U.user_id=A.cand_id', 'left')
->join('cand_job_details CJ', 'CJ.cand_id=U.user_id', 'left')
->join('designations D', 'D.designation_id=CJ.designation', 'left')
->join('countries C', 'C.id=A.country', 'left')
->join('states S', 'S.id=A.state', 'left')
->join('user_skills US', 'U.user_id=US.user_id', 'left')
->join('user_interested_cities UC', 'U.user_id=UC.user_id', 'left');
if (isset($data['designation']) && !empty($data['designation']))
{
$this->db->like('D.designation', $data['designation']);
}
if (isset($data['mode']) && !empty($data['mode']))
{
$this->db
->group_start()
->where('CJ.hiring_mode', 2)
->or_where('CJ.hiring_mode', $data['mode'])
->group_end();
}
if (isset($data['notice_period']) && !empty($data['notice_period']))
{
$this->db->where('CJ.notice_period <=', $data['notice_period']);
}
if (isset($data['city']) && !empty($data['city']))
{
$this->db->where('UC.city', $data['city']);
}
if (isset($data['skills']) && is_array($data['skills']))
{
$this->db->where_in('US.skill', $data['skills']);
}
return $this->db->get();
}
Am using dataProvider and i would like to convert a query in sql so that it follows the dataProvider way of representing data
This is the raw sql
SELECT
tblpritems.PRlineID
, tblpritems.Tracking_Code
, tblpritems.Description
, tblpritems.Quantity
, tblpritems.Unit_Price
, tblpritems.Extended_price
, tblpritems.PRID
, tblpritems.pr_solicitation_id
, tblpritems.date_item_received
, tblpritems.Quantity_received
, tblpritems.Remarks_on_receipt
, tblpritems.Received_by
FROM
prts.tblpritems
INNER JOIN prts.tblpr
ON (tblpritems.PRID = tblpr.PRID)
INNER JOIN prts.tblprsolicitations
ON (tblprsolicitations.PRID = tblpr.PRID) AND (tblpritems.pr_solicitation_id = tblprsolicitations.pr_solicitation_id)
INNER JOIN prts.tblprsuppliers
ON (tblprsuppliers.pr_solicitation_id = tblprsolicitations.pr_solicitation_id)
INNER JOIN prts.tblpo
ON (tblpo.pr_supplier_id = tblprsuppliers.pr_supplier_id)
where tblpr.PRID=".$val." and tblpo.PO_Status_ID=7 and item_received_status=0
These are the relations i have in the tblpritems
public function getPR()
{
return $this->hasOne(Tblpr::className(), ['PRID' => 'PRID']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getPrSolicitation()
{
return $this->hasOne(Tblprsolicitations::className(), ['pr_solicitation_id' => 'pr_solicitation_id']);
}
Currently am using
$dataProvider = new SqlDataProvider([
'sql' => $sql,
'pagination' => [
'pageSize' => 10,
],
]);
But the problems is that i cant access $dataProvider->getAttributes() in sql dataProvider
I would like the sql code above to be in this format
$query = Tblprsuppliers::find()
->Joinwith('prSolicitation', 'prSolicitation.pr_solicitation_id = tblprsuppliers.pr_solicitation_id')
->Joinwith('supplier', 'supplier.supplier_id = tblprsuppliers.supplier_id')
->JoinWith('currency', 'currency.CurrencyID = tblprsuppliers.currency_id ');
How can i achieve this
This is the database schema
when you have complex sql related that return instance of model you can use findBySql this way
$sql = 'SELECT
tblpritems.PRlineID
, tblpritems.Tracking_Code
, tblpritems.Description
, tblpritems.Quantity
, tblpritems.Unit_Price
, tblpritems.Extended_price
, tblpritems.PRID
, tblpritems.pr_solicitation_id
, tblpritems.date_item_received
, tblpritems.Quantity_received
, tblpritems.Remarks_on_receipt
, tblpritems.Received_by
FROM
prts.tblpritems
INNER JOIN prts.tblpr
ON (tblpritems.PRID = tblpr.PRID)
INNER JOIN prts.tblprsolicitations
ON (tblprsolicitations.PRID = tblpr.PRID) AND (tblpritems.pr_solicitation_id = tblprsolicitations.pr_solicitation_id)
INNER JOIN prts.tblprsuppliers
ON (tblprsuppliers.pr_solicitation_id = tblprsolicitations.pr_solicitation_id)
INNER JOIN prts.tblpo
ON (tblpo.pr_supplier_id = tblprsuppliers.pr_supplier_id)
where tblpr.PRID=".$val." and tblpo.PO_Status_ID=7 and item_received_status=0';
$model = Pritems::findBySql($sql)->all();
I'm new in Yii2, and I have a query with right result:
SELECT DISTINCT workloadTeam.project_id, wp.project_name, workloadTeam.user_id, workloadTeam.commit_time, wp.workload_type FROM
(SELECT p.id, p.project_name, w.user_id, w.commit_time, w.comment, w.workload_type
FROM workload as w, project as p
WHERE w.user_id = 23 AND p.id = w.project_id) wp
INNER JOIN workload as workloadTeam ON wp.id = workloadTeam.project_id
But in my ModelSearch.php, I wrote:
$user_id = Yii::$app->user->id;
$subquery = Workload::find()->select('p.id', 'p.project_name', 'w.user_id', 'w.commit_time', 'w.comment', 'w.workload_type')
->from(['project as p', 'workload as w'])
->where(['user_id' => $user_id, 'p.id' => 'w.project_id']);
$query = Workload::find()
->select(['workloadTeam.project_id', 'wp.project_name', 'workloadTeam.user_id', 'workloadTeam.from_date', 'workloadTeam.to_date', 'workloadTeam.workload_type', 'workloadTeam.comment'])
->where(['', '', $subquery]);
$query->join('INNER JOIN', 'workload as workloadTeam', 'wp.id = workloadTeam.project_id');
It happended error:
SELECT COUNT(*) FROM `workload` INNER JOIN `workload` `workloadTeam` ON wp.id = workloadTeam.project_id WHERE `` (SELECT p.project_name `p`.`id` FROM `project` `p`, `workload` `w` WHERE (`user_id`=20) AND (`p`.`id`='w.project_id'))
And I can't fix it with right query above.
You have any solution about this?
Is this error shown in the Yii-debug toolbar? Then your query (which you mentioned as error) is probably only the count from the query which is listed before.
You missed to add the sub-query in from clause like you shown in your working sql. Add this in your where clause were just the wrong place. Put sub-queries in whereconditions, if you have scalar results, because you have to use this result with operands like =, >=, in...
This could work:
$user_id = Yii::$app->user->id;
$subquery = Workload::find()->select([
'p.id as id',
'p.project_name as project_name',
'w.user_id as user_id',
'w.commit_time as commit_time',
'w.comment as comment',
'w.workload_type as workload_type'
])
->from([
'project as p',
'workload as w'
])
->where([
'user_id' => $user_id,
'p.id' => 'w.project_id'
]);
$query = Workload::find()
->select([
'workloadTeam.project_id',
'wp.project_name',
'workloadTeam.user_id',
'workloadTeam.from_date',
'workloadTeam.to_date',
'workloadTeam.workload_type',
'workloadTeam.comment'
])
->from([$subquery => 'wp']); //you were missing this line
$query->join('INNER JOIN', 'workload as workloadTeam', 'wp.id = workloadTeam.project_id');
But you don't use any selects from your workload table in your main-query $query...
Since I don't know what's your goal to achieve I can't help you at this topic...
I want To combine AND condition with OR condition in codeigniter SQL query
i am creating a where condition depending on the users input.
when a user select rent, iam passing OR condition inside WHERE(AND) like this $where['p.contract_id = 3 OR p.contract_id']=2;.
here is my code..
$where = array('p.status' => 1, 'pi.order' => 1);
if(!$fil['city'] == 0){
$where['p.city_id']=$fil['city'];
}
if(!$fil['area'] == 0){
$where['p.area_id']=$fil['area'];
}
if(!$fil['type'] == 0){
$where['p.type_id']=$fil['type'];
}
if(!$fil['bed'] == 0 && !$fil['bed']== 10){
$where['pd.bed']=$fil['bed'];
}
if($fil['bed']== 10){
$where['pd.bed >']=$fil['bed'];
}
if(!$fil['bath'] == 0 && !$fil['bath'] == 10){
$where['pd.bath']=$fil['bath'];
}
if($fil['bath'] == 10){
$where['pd.bath >']=$fil['bath'];
}
if(!is_null($fil['rent'])){
$where['p.contract_id = 3 OR p.contract_id']=2;
}
if(!is_null($fil['sale'])){
$where['p.contract_id']=1;
}
if(!$fil['price_from'] ==""){
$where['pd.price >']=$fil['price_from'];
}
//real query
$this->db->select('p.*, pd.title, pd.price, pd.bed, pd.bath, pd.size, pd.size_type, pd.full_description,
pi.name as image, pi.order, a.name as area, t.name as type_name, ct.name as contract_type, pv.views as views,
c.name as city');
$this->db->from('property p');
$this->db->join('property_detail pd', 'pd.property_id=p.property_id', 'left');
$this->db->join('property_image pi', 'pi.property_id=p.property_id', 'left');
$this->db->join('type t', 't.type_id=p.type_id', 'left');
$this->db->join('contract_type ct', 'ct.con_typ_id=p.contract_id', 'left');
$this->db->join('property_views pv', 'pv.property_id=p.property_id', 'left');
$this->db->join('area a', 'a.area_id=p.area_id', 'left');
$this->db->join('city c', 'c.city_id=p.city_id', 'left');
$this->db->where($where);
$this->db->order_by('p.property_id','desc');
$this->db->limit($config['per_page'], $this->uri->segment(3));
$query = $this->db->get();
$result = $query->result();
return $result;
ERROR
Error Number: 1064
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 '2' at line 12
SELECT 'p'.*,
'pd'.'title',
'pd'.'price',
'pd'.'bed',
'pd'.'bath',
'pd'.'size',
'pd'.'size_type',
'pd'.'full_description',
'pi'.'NAME' AS 'image',
'pi'.'ORDER',
'a'.'NAME' AS 'area',
't'.'NAME' AS 'type_name',
'ct'.'NAME' AS 'contract_type',
'pv'.'views' AS 'views',
'c'.'NAME' AS 'city'
FROM 'property' 'p'
LEFT JOIN 'property_detail' 'pd'
ON 'pd'.'property_id'='p'.'property_id'
LEFT JOIN 'property_image' 'pi'
ON 'pi'.'property_id'='p'.'property_id'
LEFT JOIN 'type' 't'
ON 't'.'type_id'='p'.'type_id'
LEFT JOIN 'contract_type' 'ct'
ON 'ct'.'con_typ_id'='p'.'contract_id'
LEFT JOIN 'property_views' 'pv'
ON 'pv'.'property_id'='p'.'property_id'
LEFT JOIN 'area' 'a'
ON 'a'.'area_id'='p'.'area_id'
LEFT JOIN 'city' 'c'
ON 'c'.'city_id'='p'.'city_id'
WHERE 'p'.'status' = 1
AND 'pi'.'ORDER' = 1
AND 'p'.'contract_id' = 3
OR p.contract_id 2
i Know very Well this error is Caused because if this $where['p.contract_id = 3 OR p.contract_id']=2;. Can some one help me to pass this where condition with OR statement in codeigniter. Tnx..
This might work for you. Here I've placed or_where() and where() after where condition which checks for your if condition
$this->db->distinct();
$this->db->select('p.*, pd.title, pd.price, pd.bed, pd.bath, pd.size, pd.size_type, pd.full_description,
pi.name as image, pi.order, a.name as area, t.name as type_name, ct.name as contract_type, pv.views as views,
c.name as city',false);
$this->db->from('property p');
$this->db->join('property_detail pd', 'pd.property_id=p.property_id', 'left');
$this->db->join('property_image pi', 'pi.property_id=p.property_id', 'left');
$this->db->join('type t', 't.type_id=p.type_id', 'left');
$this->db->join('contract_type ct', 'ct.con_typ_id=p.contract_id', 'left');
$this->db->join('property_views pv', 'pv.property_id=p.property_id', 'left');
$this->db->join('area a', 'a.area_id=p.area_id', 'left');
$this->db->join('city c', 'c.city_id=p.city_id', 'left');
$this->db->where($where);
if(!is_null($fil['rent'])){
$this->db->where('p.contract_id','3');
$this->db->or_where('p.contract_id','2');
}
$this->db->order_by('p.property_id','desc');
$this->db->limit($config['per_page'], $this->uri->segment(3));
$query = $this->db->get();
$result = $query->result();
return $result;
Output
SELECT `p`.*, `pd`.`title`, `pd`.`price`, `pd`.`bed`, `pd`.`bath`, `pd`.`size`, `pd`.`size_type`, `pd`.`full_description`, `pi`.`name` as image, `pi`.`order`, `a`.`name` as area, `t`.`name` as type_name, `ct`.`name` as contract_type, `pv`.`views` as views, `c`.`name` as city FROM (`property` p) LEFT JOIN `property_detail` pd ON `pd`.`property_id`=`p`.`property_id` LEFT JOIN `property_image` pi ON `pi`.`property_id`=`p`.`property_id` LEFT JOIN `type` t ON `t`.`type_id`=`p`.`type_id` LEFT JOIN `contract_type` ct ON `ct`.`con_typ_id`=`p`.`contract_id` LEFT JOIN `property_views` pv ON `pv`.`property_id`=`p`.`property_id` LEFT JOIN `area` a ON `a`.`area_id`=`p`.`area_id` LEFT JOIN `city` c ON `c`.`city_id`=`p`.`city_id` WHERE `p`.`status` = 1 AND `pi`.`order` = 1 AND `p`.`contract_id` = '3' OR `p`.`contract_id` = '2' ORDER BY `p`.`property_id` desc LIMIT 0
You can try something like that:
$this->db->where('(p.contract_id = 3 OR p.contract_id =2) AND (...) ', NULL, FALSE);
The third parameter tells ci that it should not try to protect your field names. You will have to care yourself for injection problems.
SELECT `p`.*, `pd`.`title`, `pd`.`price`, `pd`.`bed`, `pd`.`bath`, `pd`.`size`, `pd`.`size_type`, `pd`.`full_description`, `pi`.`name` as `image`, `pi`.`order`, `a`.`name` as `area`, `t`.`name` as `type_name`, `ct`.`name` as `contract_type`, `pv`.`views` as `views`, `c`.`name` as `city` FROM `property` `p` LEFT JOIN `property_detail` `pd` ON `pd`.`property_id`=`p`.`property_id` LEFT JOIN `property_image` `pi` ON `pi`.`property_id`=`p`.`property_id` LEFT JOIN `type` `t` ON `t`.`type_id`=`p`.`type_id` LEFT JOIN `contract_type` `ct` ON `ct`.`con_typ_id`=`p`.`contract_id` LEFT JOIN `property_views` `pv` ON `pv`.`property_id`=`p`.`property_id` LEFT JOIN `area` `a` ON `a`.`area_id`=`p`.`area_id` LEFT JOIN `city` `c` ON `c`.`city_id`=`p`.`city_id`
WHERE `p`.`contract_id` IN ('3', '2') AND `p`.`status` = 1 AND `pi`.`order` = 1 ;
I have a function that creates a query to my db, like this:
public function getList($u, $t, $ls, $lf) {
return $this->getEntityManager()
->createQuery('
SELECT
o,
u,
g,
r,
t,
p
FROM GameShelfUsersBundle:Own o
LEFT JOIN o.user u
LEFT JOIN o.game g
LEFT JOIN o.rate r
LEFT JOIN o.typo t
LEFT JOIN o.platforms p
WHERE u.id = :user
AND o.typo = :type
ORDER BY o.updated DESC
')
->setParameters(array(
'user' => $u,
'type' => $t
))
->setMaxResults($lf)
->setFirstResult($ls)
->getResult();
}
My problem is, how to set :type to be not in? I mean, I wanted to use it like this:
$type = '!= 1'
...
AND o.typo :type
...
'type' => $type
But it didn't worked at all. Using $type = -1 doesn't help either. Is there any way, other than creating if/else statement and duplicating query?
Why don't you use a query builder??
In that way you can easily customize your query, depending on some condition.
This is an example:
$q = $this
->createQueryBuilder('foo')
->select('foo')
->leftJoin('foo.bar', 'foobar')
->leftJoin('foobar.bar', 'foobarbar')
;
if($myVar > 0)
{
$q->where('foobarbar.var = :myVar');
}
else
{
$q->where('foobarbar.var = :staticValue');
}
[...]
Remember to call return $q->getResult(); at the end