after some research I created this find statement, but it doesn't work as expected:
public $virtualFields = array(
'count' => "SELECT COUNT(plans_trainings.id) FROM plans_trainings, trainings, projects WHERE plans_trainings.training_id = trainings.id AND projects.location_id = locations.id AND plans_trainings.project_id = projects.id"
);
public function trainingsPerLocationChartData(){
$this->loadModel('Locations');
$locationsDiagramData = $this->Locations->find('all', array(
'fields' => array(
'locations.id',
'locations.description',
'locations.count' /* virtuel field */
)
));
The statement will look like this:
'sql' => 'SELECT locations.id AS `locations__id`, locations.description AS `locations__description`, locations.count AS `locations__count` FROM locations Locations'
The virtual field is not recognized at all.
What do I do wrong?
UPDATE:
I found out that I have to call it like this:
'count' => "(SELECT COUNT(plans_trainings.id) FROM plans_trainings, trainings, projects WHERE plans_trainings.training_id = trainings.id AND projects.location_id = locations.id AND plans_trainings.project_id = projects.id) AS `counter`"
I added () around the select.
$locationsDiagramData = $this->Locations->find('all')
->select(['locations.id', 'locations.description', $this->virtualFields['count']]);
But I still get a wrong sql syntax:
SELECT locations.id AS `locations__id`, locations.description AS `locations__description`, (SELECT COUNT(plans_trainings.id) FROM plans_trainings, trainings, projects WHERE plans_trainings.training_id = trainings.id AND projects.location_id = locations.id AND plans_trainings.project_id = projects.id) AS `counter` AS (SELECT COUNT(plans_trainings__id) FROM plans_trainings, trainings, projects WHERE plans_trainings FROM locations Locations
The "last" problem seem only this part after AS counter:
AS (SELECT COUNT(plans_trainings__id) FROM plans_trainings, trainings,
projects WHERE plans_trainings
This is what the statement breaks!
Any ideas how to solve that?
If I run the statement in phpmyadmin and remove this mentioned part, the statement works fine and brings the right results!
UPDATE 2:
this is the plain statement:
select
locations.id,
locations.description,
(
select
count(plans_trainings.id)
from
plans_trainings,
trainings,
projects
where
plans_trainings.training_id = trainings.id
and projects.location_id = locations.id
and plans_trainings.project_id = projects.id
) as 'Anzahl'
from
locations;
try this in controller
$this->loadModel('Locations');
$this->loadModel('PlansTrainings');
$this->loadModel('Trainings');
$this->loadModel('Projects');
$sub_query=$this->PlansTrainings->find()->select(['cnt1'=>'count(PlansTrainings.id)'])->join([
[
'table' => 'trainings',
'alias' => 'Trainings',
'type' => 'INNER',
'conditions' => 'PlansTrainings.training_id=Trainings.id',
],
[
'table' => 'projects',
'alias' => 'Projects',
'type' => 'INNER', //LEFT, RIGHT...
'conditions' => ['Projects.location_id=PlansTrainings.id','PlansTrainings.project_id=Projects.id'],
],
]);
$locationsDiagramData = $this->Locations->find()->select(['id', 'description','count'=>$sub_query]);
Related
I have following situation.
i have a table "drivers_events" in this there are stored the drivers which are booked for an event.
Now I would like to do following
SELECT
Driver.id,
Driver.name
FROM
drivers AS Driver
INNER JOIN
drivers_events AS Listing
ON Driver.id = Listing.driver_id
WHERE
Listing.event_id = 83
ORDER BY
Driver.name ASC;
If I run it as a SQL query in phpmyadmin, it works perfectly and I get the correct id and name from the table "drivers".
When I do this in my controller like this
$drivers = $this->Jobs->query("
SELECT
Driver.id,
Driver.name
FROM
drivers AS Driver
INNER JOIN
drivers_events AS Event
ON Driver.id = Event.driver_id
WHERE
Event.event_id = $activeevent
ORDER BY
Driver.name ASC
");
then i get the complete array of jobs which created in the past.
What did i do wrong ?
It would be great if someone could help me.
Thanks in advance
I tried a lot more. I have come to the conclusion that I can read out the drivers who are assigned to an event.
in the controller it looks like this
$drivers = $this->Jobs->drivers_events->find('list',
[
'conditions' =>
[
'drivers_events.event_id' => $this->request->session()->read('Event.active')
],
'keyField' => 'driver_id',
'valueField' => 'driver_id'
]
);
In the model
$this->belongsTo('drivers_events', [
'foreignKey' => 'event_id',
]);
So now I get the right drivers for a driving job within an event.
But how do I get the name of the driver from the "Drivers" table instead the ID ?
Thx for help
Event key word is reserved for SQL.
Please do not use it for table alias.
Or use such this method.
drivers_events AS `Event`
Hope to be useful.
$result = $this->Jobs->find()
->enableAutoFields(true)
->enableHydration(false)
->select([
'id' => 'Driver.id',
'Title' => "Driver.name"
])
->join([
'Events' => [
'table' => 'drivers_events',
'type' => 'INNER',
'conditions' => [
'Jobs.event_id = Events.id',
],
]
])
->join([
'Driver' => [
'table' => 'drivers',
'type' => 'INNER',
'conditions' => [
'Events.driver_id = Driver.id',
],
]
])
->where([
'Events.id' => $activeevent
])
->group('Driver.id')
->toArray();
Ref: Cakephp 3 Adding Joins
Select Drivers.id, drivers.accountname
FROM TABLE__
Join table__
Join table__
And (Brand) Totaljobs.com
Having Count <4
group By Driver.id, Drivers.Accountname
Order by (Drivers.accountname)
i need to use yii1 CGridView with the custom SQL.
i have followed this article
inside model I've created
public function searchUserStats()
{
$count = Yii::app()->db->createCommand()
->select('count(DISTINCT user_id)')
->from('casino_sg_sessions')
->queryScalar();
$sql = '
SELECT
SUM(bet) bet_sum,
SUM(win) win_sum,
SUM(bet_count) bet_count,
user_id,
userName,
modified
FROM
(SELECT
(SELECT IFNULL(SUM(tr1.amount), 0) FROM casino_sg_transactions tr1 WHERE t.id = tr1.session_id AND tr1.action = \'bet\' ) AS bet,
(SELECT IFNULL(SUM(tr2.amount), 0) FROM casino_sg_transactions tr2 WHERE t.id = tr2.session_id AND tr2.action = \'win\' ) AS win,
(SELECT count(0) FROM casino_sg_transactions tr3 WHERE t.id = tr3.session_id) AS bet_count,
t.user_id,
u.userName,
t.modified
FROM `casino_sg_sessions` t
INNER JOIN user u ON u.id = t.user_id
ORDER BY modified DESC
) user_stats
GROUP BY user_id
ORDER BY modified DESC
';
$command = Yii::app()->db->createCommand($sql);
$dataProvider = new CSqlDataProvider($command, array(
'totalItemCount'=>$count,
'pagination'=>array(
'pageSize'=>15,
),
));
return $dataProvider;
}
in the controller:
$model = new CasinoSgSessions('searchUserStats');
$this->render('index', array(
'model' => $model,
));
inside the view i call it this way:
$this->widget('application.widgets.grid.CGridView', array(
'dataProvider' => $model->searchUserStats(),
'filter' => $model,
'columns' => array(
[
'header' => 'User ID',
'name' => 'user_id',
'value' => '$data->user_id',
'htmlOptions' => array('width'=>'150px'),
],
.....
.....
i receive paginated grid without data.
spent huge amount of time and now gave up, what i did wrong ?
sql query itself works good.
PS: i cant use mysql views and create model for the view.
PPS: query will be a bit more complex, so the only way i see is using CGridView through the sql query.
in the template instead of
$data->user_id
i had to use
$data['user_id']
absolutely not expected behavior. Seems to me they didn't hear about SOLID
I want to convert following complex mysql into cake's find expression:
SELECT p1, p2
FROM
(
SELECT IFNULL(a.c2, '10') AS p1, IFNULL((SELECT MAX(c.c1) FROM my_table c WHERE c.c1>p1), '30') AS p2
FROM my_table a
WHERE
(
(a.user_id = 2) AND (a.c1 BETWEEN '10' AND '30')
)
) as temp
WHERE p2 > 100
ORDER BY p1;
I tried following
http://dogmatic69.com/sql-to-cakephp-find-converter
but unable to generate the desired expression.
Please help. I really don't know how to handle such complex expressions (I do not prefer to use query in cakephp)
Thanks
Let me just convert your query into the cakephp way
if table a's model is A:
$fields = "IFNULL(A.c2, '10') AS p1, IFNULL((SELECT MAX(C.c1) FROM my_table c WHERE C.c1>p1), '30') AS p2";
$conditions = "A.user_id=2 AND A.c1 BETWEEN '10' AND '30'";
$inner_querry = $this->A->find("all", compact("fields", "conditions"));
$fields = "p1,p2";
$conditions = "p1 IN ($inner_querry) AND p2 IN($inner_query) AND p2 > 100";
$order = "p1";
$query = $this->A->find("all", compact("fields", "conditions", "order"));
debug($query); //check results of for error.
I think that sometimes it's not so wrong to use Model->query(), but let' try to use cake functions.
In fact the only way I see to obtain that particular query is building the subqueries with buildStatement() function (and at the end you still have to call Model->query() so...). But just for fun.
Assuming your model name is MyTable, in your MyTablesController do:
$p1 = "IFNULL(a.c2, '10') AS p1";
$db = $this->MyTable->getDataSource();
$subQuery = $db->buildStatement(
array(
'table' => $db->fullTableName($this->MyTable),
'alias' => 'C',
'fields' => array('MAX(c.c1)'),
'conditions' => array(
"C.c1 > " => 'p1',
)
),
$this->MyTable
);
$p2 = "IFNULL(".$subQuery.") AS p2";
$subQuery = $db->buildStatement(
array(
'table' => $db->fullTableName($this->MyTable),
'alias' => 'A',
'fields' => array($p1, $p2),
'conditions' => array(
"A.user_id" => 2,
"A.c1 BETWEEN ? AND ?" => array(10,30)
)
),
$this->MyTable
);
$query = $db->buildStatement(
array(
'table' => $subQuery,
'alias' => 'test',
'fields' => array('p1', 'p2'),
'conditions' => array(
"p2 > " => 100,
)
),
$this->MyTable
);
below shown is my mysql query.it works well. but I need to do that in cakephp. how can I convert this into cake php
SELECT pp.product_properties_id,ppv.product_property_value_id FROM product_properties pp
INNER JOIN product_property_values ppv ON pp.product_properties_id = ppv.properties_id
WHERE pp.property_name='Color' AND ppv.properties_value='Blue'
please help me..
The cookbook explains how to do this: http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#joining-tables
$query_options = array();
$query_options['fields'] = array( 'pp.product_properties_id', 'ppv.product_property_value_id' );
$query_options['conditions'] = array( 'pp.property_name' => 'Color' , 'ppv.properties_value' => 'Blue');
$query_options['joins'] = array('table' => 'product_property_values',
'alias' => 'ppv',
'type' => 'INNER',
'conditions' => array(
'ppv.id = pp.ppv_id',
)
);
$result = $this->pp->find('all', $query_options);
I want to run a query which calculate sum for a particular columns. for this i need to join two table that will map the matched records and give the results. Below i paste my query please correct me where i am wrong in my query..
it may be mapping twice so it shows wrong result.
$this->Inventory->find('all',array('joins'=>array(
array('table' => 'items',
'alias' => 'item',
'type' => 'left',
'conditions' => array(
'Inventory.item_id = item.id')
),
array('table' => 'material_owners',
'alias' => 'owner',
'type' => 'left',
'conditions' => array(
'Inventory.material_owner_id = owner.id')
),
array('table' => 'projects',
'alias' => 'project',
'type' => 'left',
'conditions' => array(
'Inventory.project_id = project.id')
),
array('table' => 'material_payments',
'alias' => 'mp',
'type' => 'left',
'conditions' => array(
'Inventory.material_owner_id=mp.material_owner_id'),
),
),
'conditions'=>array('Inventory.project_id'=>$project_id),
'fields' =>array('sum(Inventory.total_amount) as total_amount','sum(mp.paid_amount) as paid_amount','item.name','item.id','owner.id','owner.first_name','owner.last_name','project.id','project.name'),
'group'=> array('item.name','item.id','owner.id','owner.first_name','owner.last_name','project.name','project.id')
)
);
This is the result query generated by cakephp.
SELECT sum("Inventory"."total_amount") as total_amount, sum("mp"."paid_amount") as paid_amount, "item"."name" AS "item__name", "item"."id" AS "item__id", "owner"."id" AS "owner__id", "owner"."first_name" AS "owner__first_name", "owner"."last_name" AS "owner__last_name", "project"."id" AS "project__id", "project"."name" AS "project__name" FROM "inventories" AS "Inventory" left JOIN "items" AS "item" ON ("Inventory"."item_id" = "item"."id") left JOIN "material_owners" AS "owner" ON ("Inventory"."material_owner_id" = "owner"."id") left JOIN "projects" AS "project" ON ("Inventory"."project_id" = "project"."id") left JOIN "material_payments" AS "mp" ON ("Inventory"."material_owner_id" = "mp"."material_owner_id") LEFT JOIN "items" AS "Item" ON ("Inventory"."item_id" = "Item"."id") LEFT JOIN "units" AS "Unit" ON ("Inventory"."unit_id" = "Unit"."id") LEFT JOIN "projects" AS "Project" ON ("Inventory"."project_id" = "Project"."id") LEFT JOIN "material_owners" AS "MaterialOwner" ON ("Inventory"."project_id" = "MaterialOwner"."id") WHERE "Inventory"."project_id" = '4' GROUP BY "item"."name", "item"."id", "owner"."id", "owner"."first_name", "owner"."last_name", "project"."name", "project"."id"
I'm not sure what you're trying to achive here. Does your cake query work at all?
What errors do you get or how do you want the output to be?
For a sollution, I'd take a look at virtualfields.
http://book.cakephp.org/2.0/en/models/virtual-fields.html
They can be added to each model prior to your query with the joins.