I have multiple query in foreach i know its wrong and i want to correct it i have virtual_fields like this:
'night_hours' => 'SUM(Hour.night)',
'half_hours' => 'SUM(Hour.half)',
'NN' => 'SUM(Hour.day_off_id = 13)'
my foreach loop in controller:
foreach ($users as $user){
$set_of_days = $this->Hour->find('all', array(
'fields' => array('hour_from', 'hour_to', 'day_off_id', 'night_hours', 'half_hours', 'NN'),
'conditions' =>
array('subordinate_id' => $user['User']['id'],
'date(Hour.date) BETWEEN ? AND ?' => array($date_from, $date_to))));
its working fine but when i'll have 4k users in one view it will kill db, i wanted to join with table users with hours but i get error that column night_hours don't exist, do you guys know any way around?
Here is one of queries :
SELECT `Hour`.`hour_from`, `Hour`.`hour_to`, `Hour`.`day_off_id`, (SUM(`Hour`.`night`)) AS `Hour__night_hours`, (SUM(`Hour`.`half`)) AS `Hour__half_hours`, (SUM(`Hour`.`day_off_id` = 13)) AS `Hour__NN` FROM `kadry`.`hours` AS `Hour` WHERE `subordinate_id` = 193 AND date(`Hour`.`date`) BETWEEN '2014-01-11' AND '2014-02-11'
You dont have thiese columns 'night_hours', 'half_hours' , in your query you gave it different alias
try this
'fields' => array('hour_from', 'hour_to', 'day_off_id', 'Hour__night_hours', 'Hour__half_hours', 'NN'),
you ave aliases like that in your query
SELECT `Hour`.`hour_from`,
`Hour`.`hour_to`,
`Hour`.`day_off_id`,
(SUM(`Hour`.`night`)) AS `Hour__night_hours`,
^^^^^^^^^^^^^^^^^^^//---> here your alias
(SUM(`Hour`.`half`)) AS `Hour__half_hours`,
^^^^^^^^^^^^^^^^^^ //---> here your alias
......
......
Related
I have some problems with the limit using active record.
I've created a dataProvider with a limit of 5:
$dataProvider = new ActiveDataProvider([
'query' => Devicesdb::find()
->joinWith('score')
->where('devices.devicetype = :deviceType', [':deviceType' => $device])
->orderBy(['score' => SORT_DESC])
->limit(5),
'totalCount' => 5,
]);
And this is the resultant query in debug panel:
SELECT `devicesdb`.*
FROM `devicesdb`
LEFT JOIN `devices`
ON `devicesdb`.`id` = `devices`.`id`
WHERE devices.devicetype = 'phone'
ORDER BY `score`
DESC LIMIT 20
The query is fine , and retourns me the data as I want, but I only want 5 items, not 20.
First of all totalCount is a property of Pagination, not ActiveDataProvider. You need to nest it inside of a pagination configurational array. But this is not how you achieve this.
Because you don't want the pagination to appear you can disable it by passing false and now limit will be taken from query (otherwise it's ignored and calculated differently, you can see this related question):
$dataProvider = new ActiveDataProvider([
'query' => Devicesdb::find()
->joinWith('score')
->where('devices.devicetype = :deviceType', [':deviceType' => $device])
->orderBy(['score' => SORT_DESC])
->limit(5),
'pagination' => false,
]);
]);
One more thing - you don't have to write params manually, see this question for explanation and better understanding. So where part of the query can be reduced to just:
->where(['devices.devicetype' => $device])
Also I recommend to refactor model name to just Device and use this to resolve duplicate names conflicts (if any) in SQL query:
->where(Device::tableName() . 'devicetype' => $device])
That way if this model related table name will changed in the future, you don't have to refactor your code.
First of all, hello there !=)
I was wondering if anyone knew how to write a select in a where such as
SELECT my_column
FROM my_table
WHERE field_1 = something
AND field_2 = ( SELECT field_2
FROM my_table_2
WHERE my_field = $myParam );
I know how to write this query without the select :
//This part shouldn't matter, it's just my way of connecting to table database
$select = $mytable1->getTableGateway()->getSQL()->select();
//This is where the fun begin
$select->colunms(array('my_column'))
->where(array('field_1' => 'something', 'field_2' => ??);
TRY 1 :
Using another variable that allows me to connect to the other base doesn't seem to work because of course it's not a array or anything...
$select_2 = $myTable2->tableGateway->getSQL()->select();
$select_2->colunms(array('field_2'))
->where(array('my_field' => $myParam);
$select->colunms(array('my_column'))
->where(array('field_1' => 'something', 'field_2' => $select_2);
I tried adding something like :
$var= $myTable2->getTableGateway()->selectWith($select_2);
//and then
$select->colunms(array('my_column'))
->where(array('field_1' => 'something', 'field_2' => $var->toArray());
It doesn't work either, because of course it's not one line...
I don't think a foreach is really necessary
Any thought before i go too far in my thoughts ?
Thank in advance
In ZF1 it works like this:
$select_2 = $myTable2->tableGateway->getSQL()->select();
$select_2->columns(array('field_2'))
->where(array('my_field = ?' => $myParam);
$select->columns(array('my_column'))
->where(array('field_1 = ?' => 'something', 'field_2 = ?' => $select_2)
Honestly, I'm not sure if it'll work in ZF2, but try to add the wildcard '?' to your where clause.
Best,
I have a stream/table named profiles. All of its column are stream-fields. I am trying to restrict the result returned by the the function, get_entries() depending on some criteria. Below is my code:
$data = [
'stream' => 'profiles',
'namespace' => 'users',
'where' => 'user_id = 3' // lets say, this is my criteria
];
$row = $this->streams->entries->get_entries($data); // returns empty
The varaible, $row resulted in empty array. Although there is one row in table, profiles where user_id is 3. I have read the documentation of pyrocms and it pretty much says the exact way to use the where clause (just like above).
NOTE: I have also tried writing like
'where' => 'profiles.user_id = 3'`
joy !to avoid table conflict. Still no
But when I write the code like this:
$row = $this->streams->entries->get_entries($query);
$query = [
'stream' => 'profiles',
'namespace' => 'users'
];
// No where clause this time
$row = $this->streams->entries->get_entries($query);
This time $row returns all rows including the row with user id 3.
I am unable to use the where clause in get_entries in a right way. I might have done some mistake. Help me out guyz
NOTE: I am using community edition.
I think this might be due to a bug (well, not a bug, but a feature that doesn't work as intended).
If I'm intentionally issue a wrong query, the sql query output is
SELECT [ ... ] LEFT JOIN `default_profiles` as `profiles` ON `profiles`.`user_id`=`default_profiles`.`created_by` WHERE (user_id` = 1) ORDER BY `default_profiles`.`created` DESC
Here you see that PyroCMS tries to lookup the data for the "created_by" field. And that doesn't work in this case.
If you disable the 'created_by' field, you should get the correct row:
$this->streams->entries->get_entries(
array(
'stream' => 'profiles',
'namespace' => 'users',
'where' => 'user_id = 3',
'disable' => 'created_by'
)
);
It would be great if you could file an issue on the pyrocms github page. If you won't I'll do it in the next few days.
Model
public function get_entries($table, $where) {
$this->db->select('*');
$this->db->from($table);
foreach ($where as $key => $value) {
$this->db->where($key, $value);
}
$this->query = $this->db->get();
foreach ($this->query->result_array() as $row) {
$array1[] = $row;
}
if ($this->query->num_rows() == 0)
return false;
else
return $array1;
}
call this model function as
$row = $this->streams->entries->get_entries('profiles',array('user_id '=>3));
I have a very complex setup on my tables and achieving this via any of the find() methods is not an option for me, since I would need to fix relationships between my tables and I don't have the time right now, so I'm looking for a simple fix here.
All I want to achieve is run a query like this:
SELECT MAX( id ) as max FROM MyTable WHERE another_field_id = $another_field_id
Then, I need to assign that single id to a variable for later use.
The way I have it now it returns something like [{{max: 16}}], I'm aware I may be able to do some PHP on this result set to get the single value I need, but I was hoping there was already a way to do this on CakePHP.
Assuming you have a model for your table and your are using CakePHP 2.x, do:
$result = $this->MyTable->field('id', array('1=1'), 'id DESC');
This will return a single value.
see Model::field()
This example is directly from the CakePHP documentation. it seems you can use the find method of a model to get count
$total = $this->Article->find('count');
$pending = $this->Article->find('count', array(
'conditions' => array('Article.status' => 'pending')
));
$authors = $this->Article->User->find('count');
$publishedAuthors = $this->Article->find('count', array(
'fields' => 'DISTINCT Article.user_id',
'conditions' => array('Article.status !=' => 'pending')
));
I have two models in an 1:n relation and I just want to load the count of the related items.
First one is the table/model "Ad" (one) which is related to "AdEvent" (many). AdEvents has a foreign key "ad_id".
In the controller I can use it that way and it loads the related AdEvent-records.
$this->Ad->bindModel(array('hasMany' => array(
'AdEvent' => array(
'className' => 'AdEvent',
'foreignKey' => 'ad_id',
))));
Now I just need the count without the data and I tried with param "fields" and "group" a COUNT()-statement, but in that case the result is empty. I also changed the relation to "hasOne", but no effect.
Any idea how to use the Cake-magic to do that?
EDIT:
With simple SQL it would look like this (I simplyfied it, a.id instead of a.*):
SELECT a.id, COUNT(e.id) AS count_events
FROM cake.admanager_ads AS a
JOIN ad_events AS e ON e.ad_id = a.id
GROUP BY a.id
LIMIT 50;
You can always do a manual count of course. This is what I almost always end up doing because I almost always have the data loaded already for some other purpose.
$Ads = $this->Ad->find('all')
foreach ($Ads as $Ad) {
$NumAdEvents = array(
$Ad['Ad']['id'] => sizeof($Ad['AdEvents']),
)
}
debug($NumAdEvents);
die;
Or you can use a find('count'):
$id_of_ad = 1; //insert your ad id here, or you can search by some other field
$NumAdEventsAtOneAd = $this->AdEvent->find('count', array('conditions' => array(
'AdEvent.ad_id' => $id_of_ad,
)));
debug($NumAdEventsAtOneAd);
die;