order and limit on a select query zend framework 2 - mysql

Earlier this day a asked a question about an update query. But now i want to select some things ( and it is working ) but I also want to order them and put a limit on it.
This is the code to select all the food :
public function getFood($id)
{
$id = (int)$id;
$rowset = $this->tableGateway->select(array('kindOfFood_id' => $id));
$row = $rowset->current();
if (!$row) {
throw new \Exception("Could not find row $id");
}
return $row;
}
But how can i do this :
Select * from KindOfFood ==> order by kindOfFood_votes DESC ?
I saw on the documentation you can do something like this, but it doesn't work with me?
$rowset = $artistTable->select(function (Select $select) {
$select->where->like('name', 'Brit%');
$select->order('name ASC')->limit(2);
});

Are you looking to return only single row or multiple rows.
Try this for multiple rows -
use Zend\Db\Sql\Select; //at the top of the page among other use statements.
public function getFood($id)
{
$id = (int) $id;
$select = new Select(TABLE_NAME); //CHANGE TABLE_NAME as per needs
$select->where('kindOfFood_id = ' . $id);
$select->order('kindOfFood_votes DESC');
$resultSet = $this->tableGateway->selectWith($select); //Will get array of rows.
//$row = $rowset->current(); THIS IS FOR RETURNING ONLY SINGLE ROW NOT ALL ROWS
if (!$resultSet) {
throw new \Exception("Could not find rows with food id - $id");
}
return $resultSet;
}
Can access the returned resultSet via loop. Eg: foreach
foreach($resultSet as $row) {
echo $row->kindOfFood_id; //or something
}
Note:
If you need only
Select * from KindOfFood order by kindOfFood_votes DESC
then remove the $select->where('kindOfFood_id = ' . $id); line from above.

Related

How to convert sql query to codeigniter query

Can somebody help me convert this Sql Query
SELECT *
FROM customer c
LEFT JOIN customer_order co
ON c.customer_number = co.customer_number
AND co.order_status IN ('preparing', 'prepared')
WHERE c.customer_status='unpaid'
AND c.order_status = 'unserve'
AND co.cus_ord_no IS null
into Codeigniter query just like the image below for example
When query statements do not have clauses that need to change conditionally then using $this->db-query() is the way to go.
$sql = "SELECT * FROM customer c LEFT JOIN customer_order co
ON c.customer_number=co.customer_number AND co.order_status IN ('preparing', 'prepared')
WHERE c.customer_status='unpaid' AND c.order_status='unserve' AND co.cus_ord_no IS null";
$query = $this->db->query($sql)->result();
echo json_encode($query);
It might be wise to include a check on the return from query() though because if it fails (returns false) then the call to result() will throw an exception. One way that can be handled is like this.
$query = $this->db->query($sql);
if($query !== FALSE)
{
echo json_encode($query->result());
return;
}
echo json_encode([]); // respond with an empty array
Query Builder (QB) is a nice tool, but it is often overkill. It adds a lot of overhead to create a string that literally is passed to $db->query(). If you know the string and it doesn't need to be restructured for some reason you don't need QB.
QB is most useful when you want to make changes to your query statement conditionally. Sorting might be one possible case.
if($order === 'desc'){
$this->db->order_by('somefield','DESC');
} else {
$this->db->order_by('somefield','ASC');
}
$results = $this->db
->where('other_field', "Foo")
->get('some_table')
->result();
So if the value of $order is 'desc' the query statement would be
SELECT * FROM some_table WHERE other_field = 'Foo' ORDER BY somefield 'DESC'
But if you insist on using Query Builder I believe this your answer
$query = $this->db
->join('customer_order co', "c.customer_number = co.customer_number AND co.order_status IN ('preparing', 'prepared')", 'left')
->where('c.customer_status','unpaid')
->where('c.order_status','unserve')
->where('co.cus_ord_no IS NULL')
->get('customer c');
//another variation on how to check that the query worked
$result = $query ? $query->result() : [];
echo json_encode($result);
You can do
public function view_customers()
{
$sql = "SELECT * FROM customer c LEFT JOIN customer_order co ON c.customer_number = co.customer_number AND co.order_status IN ('preparing', 'prepared') WHERE c.customer_status='unpaid' AND c.order_status = 'unserve' AND co.cus_ord_no IS null";
return $this->db->query($sql)->result();
}
You can use row() for one output to object, or row_array() if one output but array. result() is multiple objects and result_array() is multiple arrays.
My way do usually is like this:
Controller:
public function view()
{
$this->load->model('My_Model');
$data = new stdclass;
$data->user_lists = $this->my_model->view_users(array('nationality'=>'AMERICAN'));
}
Model:
public function view_users($param = null) //no value passed
{
$condition = '1';
if (!empty($param)) { //Having this will trap if you input an array or not
foreach ($param as $key=>$val) {
$condition .= " AND {$key}='{$val}'"; //Use double quote so the data $key and $val will be read.
}
}
$sql = "SELECT * FROM users WHERE {$condition}"; //Use double quote so the data $condition will be read.
// Final out is this "SELECT * FROM users WHERE 1 AND nationality='AMERICAN'";
return $this->db->query($sql)->result();
}

Mysql PDO (Getting total from all colums) [duplicate]

I'm new to php and I've searched for the past hour and read all the documentation I could find and nothing is helping. I have a table that has a bunch of rows of data. I'm trying to pick one column from the whole table and add them all together. Here is what I got. All this tells me is how many rows there are that match my query, not the total sum of column I want. Any help is appreciated.
$res1 = $db->prepare('SELECT sum(distance) FROM trip_logs WHERE user_id = '. $user_id .' AND status = "2"');
$res1->execute();
$sum_miles = 0;
while($row1 = $res1->fetch(PDO::FETCH_ASSOC)) {
$sum_miles += $row1['distance'];
}
echo $sum_miles;
You're only returning one row in this instance. Modify your summed column to have an alias:
SELECT SUM(distance) AS totDistance FROM trip_logs ....
Now you can can fetch the row -
$row = $res1->fetch(PDO::FETCH_ASSOC);
echo $row['totDistance'];
No need to loop.
You can use SUM() without explicitely grouping your rows because if you use a group function in a statement containing no GROUP BY clause, it is equivalent to grouping on all rows.
If however you want to use the SUM() function for something slightly more complicated you have to group your rows so that the sum can operate on what you want.
If you want to get multiple sums in a single statement, for example to get the distance for all users at once, you need to group the rows explicitely:
$res1 = $db->prepare("
SELECT
SUM(distance) AS distance,
user_id
FROM trip_logs WHERE status = '2'
GROUP BY user_id
");
$res1->execute();
while ($row = $res1->fetch(PDO::FETCH_ASSOC))
{
echo "user $row[user_id] has runned $row[distance] km.\n";
}
This will return the sum of distances by user, not for all users at once.
Try this if you are using a Class :
class Sample_class{
private $db;
public function __construct($database) {
$this->db = $database;
}
public function GetDistant($user_id,$status) {
$query = $this->db->prepare("SELECT sum(distance) FROM trip_logs WHERE user_id =? AND status =?");
$query->bindValue(1, $user_id);
$query->bindValue(2, $status);
try{ $query->execute();
$rows = $query->fetch();
return $rows[0];
} catch (PDOException $e){die($e->getMessage());}
}
}
$dist = new Sample_class($db);
$user_id = 10;
$status = 2;
echo $dist->GetDistant($user_id,$status);

How to set sql_mode in Zend Framework 2?

I'm currently having an issue with pagination in Zend Framework 2.
This code
public function findAllByCriteria(CourseSearchInput $input) {
$concatDelimiter = self::CONCAT_DELIMITER;
$select = new Select();
$where = new Where();
$having = new Having();
$select->columns(array(
'id', 'title', 'description'
));
$select->from($this->tableGateway->getTable());
$select
->join('coursedata', 'courses.id = coursedata.id', array(
'relevance' => $this->buildRelevanceExpressionFromCriteria($input)
))
;
$having
->greaterThanOrEqualTo('relevance', self::RELEVANCE_MIN);
;
$select->where($where, Predicate::OP_AND);
$select->having($having);
$select->group(array('courses.id'));
$dbAdapter = $this->tableGateway->getAdapter();
// $dbAdapter->getDriver()->getConnection()->execute('SET sql_mode = "";');
$adapter = new \Zend\Paginator\Adapter\DbSelect($select, $dbAdapter);
$paginator = new \Zend\Paginator\Paginator($adapter);
return $paginator;
}
create this SQL:
SELECT
`courses`.`id` AS `id`,
`courses`.`title` AS `title`,
`courses`.`description` AS `description`,
MATCH (coursedata.title) AGAINST ('Salsa') * 5 + MATCH (coursedata.description) AGAINST ('Salsa') * 2 AS `relevance`
FROM `courses`
INNER JOIN `coursedata` ON `courses`.`id` = `coursedata`.`id`
GROUP BY `courses`.`id`
HAVING `relevance` >= '3'
It ueses the MySQL Extensions to GROUP BY and cannot be executed, if the sql_mode is set to ONLY_FULL_GROUP_BY. So, I tried to reset the sql_mode before the statement is executed (see the commented out line above: $dbAdapter->getDriver()->getConnection()->execute('SET sql_mode = "";');). But it didn't worked. So, how can I set the sql_mode in order to execute my non-standard SQL?
This may not be the answer to the question you are asking, but I can see you are going to have an issue with your query regardless when using Paginator.
The DbSelect Adapter for the Paginator doesn't like the aggregate function in there (Group By)
The Paginator will try and use your query to build it's own query to calculate the "count" for items in the collection. This is broken due to you using an aggregate in your query, any groups etc will break the adapter.
if you check the default implementation you will see:
/**
* Returns the total number of rows in the result set.
*
* #return integer
*/
public function count()
{
if ($this->rowCount !== null) {
return $this->rowCount;
}
$select = clone $this->select;
$select->reset(Select::COLUMNS);
$select->reset(Select::LIMIT);
$select->reset(Select::OFFSET);
// This won't work if you've got a Group By in your query
$select->columns(array('c' => new Expression('COUNT(1)')));
$statement = $this->sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
$row = $result->current();
$this->rowCount = $row['c'];
return $this->rowCount;
}
this doesn't like when you are using Group BY and will give back incorrect results.
You can create your own adataper, and extend the existing DbSelect and override the count method when you are planning to use Group BY;
Off the top of my head something like this should work, but may not be the most efficient way of doing it
/**
* Returns the total number of rows in the result set.
*
* #return integer
*/
public function count()
{
if ($this->rowCount !== null) {
return $this->rowCount;
}
/**
* If the query hasn't got 'GROUP BY' just try and use the old method
*/
$stateGroup = $this->select->getRawState('group');
if( ! isset($stateGroup) || empty($stateGroup)) {
return parent::count();
}
$select = clone $this->select;
$select->reset(Select::LIMIT);
$select->reset(Select::OFFSET);
$statement = $this->sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
$this->rowCount = $result->count();
return $this->rowCount;
}

How to use 'distinct' in zend db model

I have search for a long time to get this thing work.
What I want is to know how I user the 'distinct' in a zend db model to make my selection for the followers of a user unique.
My db model to count followers for a user (here I need to add the 'distinct')
public function countFollowers($user_id)
{
$rowset = $this->fetchAll("user_id = $user_id");
$rowCount = count($rowset);
if ($rowCount > 0) {
return $rowCount;
} else {
return $rowCount;
}
}
EDIT: This function is part of 'class Application_Model_DbTable_Followers extends Zend_Db_Table_Abstract'
My table structure
id
article_id // Id of the article who is written by 'user_id'.
user_id // user_id owner of the article
follower_id // member who has following this article
date // date of follow
'user_id' can be written various articles, the follower can follow various articles of the same writer. I want to make a unique follower count. As an example what I want, If a follower is following 8 articles of one writer it has to be compared to '1' in the count.
I hope this will be clear enough to understand what I tried to reach.
With kind regards,
Nicky
Using distinct:
public function countFollowers($user_id)
{
$select = $this->select()
->distinct()
->where('user_id = ?', $user_id);
$rowset = $this->fetchAll($select);
$rowCount = count($rowset);
return $rowCount;
}
EDIT: After edit in question to get count of followers of a user. You actually need to use group NOT distinct. I have tested the following query works to fetch the data to be count()ed,
SELECT * FROM followers WHERE user_id = 1 GROUP BY user_id,
follower_id
I have not tested the code, but something like this should work:
public function countFollowers($user_id)
{
$select = $this->select()
->where('user_id = ?', $user_id)
->group(array('user_id', 'follower_id'));
$rowset = $this->fetchAll($select);
$rowCount = count($rowset);
return $rowCount;
}
You can specify mysql functions in the 'from' function that makes up select query function. To use the from function you need to pass the table name as the first parameter, however passing $this (your table model class) works fine.
public function countFollowers($user_id)
{
$rowset = $this->fetchAll(
$this->select()
->from($this, array('DISTINCT user_id'))
->where('user_id = ?', $user_id)
);
return count($rowset);
}
[edit]
Based on your edit, 'group' may also work for you:
public function countFollowers($user_id)
{
$rowset = $this->fetchAll(
$this->select()
->where('user_id = ?', $user_id)
->group('user_id')
);
return count($rowset);
}
This will group all matching user_id into one record. So if a user is found, it will return 1, else 0.
Retrieving all the rows simply to get a count strikes me as overkill.
You can do a count using something like this:
$select = $db->select();
$select->from('testcount', new Zend_Db_Expr('COUNT(id)'))
->where('user_id = ?', $someUserId);
return $db->fetchOne($select);
don't write that :
public function countFollowers($user_id)
{
$rowset = $this->fetchAll(
$this->select()
->from($this, array('DISTINCT user_id'))
->where('user_id = ?', $user_id)
);
return count($rowset);
}
But that :
public function countFollowers($user_id)
{
$rowset = $this->fetchAll(
$this->select()
->from($this, array('DISTINCT(user_id)'))
->where('user_id = ?', $user_id)
);
return count($rowset);
}
Else you will have an error wich looks like to Mysqli prepare error:
Unknown column 'repertoire.distinct idRepertoireParent' in 'field list'
Also we have one method from the official manual
Just use "distinct"
Build this query: SELECT DISTINCT p."product_name" FROM "products" AS p
$select = $db->select()
->distinct()
->from(array('p' => 'products'), 'product_name');
Today I tried DISTINCT in JOIN LEFT case and it doesn't work. But if you add a Group By to the DISTINCT column, it works fine.

Zend_Db: How to get the number of rows from a table?

I want to find out how many rows are in a table. The database that I am using is a MySQL database. I already have a Db_Table class that I am using for calls like fetchAll(). But I don't need any information from the table, just the row count. How can I get a count of all the rows in the table without calling fetchAll()?
$count = $db->fetchOne( 'SELECT COUNT(*) AS count FROM yourTable' );
Counting rows with fetchAll considered harmful.
Here's how to do it the Zend_Db_Select way:
$habits_table = new Habits(); /* #var $habits_table Zend_Db_Table_Abstract */
$select = $habits_table->select();
$select->from($habits_table->info(Habits::NAME), 'count(*) as COUNT');
$result = $habits_table->fetchRow($select);
print_r($result['COUNT']);die;
Proper Zend-Way is to use Zend_Db_Select like this:
$sql = $table->select()->columns(array('name', 'email', 'status'))->where('status = 1')->order('name');
$data = $table->fetchAll($sql);
$sql->reset('columns')->columns(new Zend_Db_Expr('COUNT(*)'));
$count = $table->getAdapter()->fetchOne($sql);
This is how it's done in Zend_Paginator. Other option is to add SQL_CALC_FOUND_ROWS before your column list and then get the number of found rows with this query:
$count = $this->getAdapter()->fetchOne('SELECT FOUND_ROWS()');
You could do a
SELECT COUNT(*)
FROM your_table
$dbo->setFetchMode( Zend_Db::FETCH_OBJ );
$sql = 'SELECT COUNT(*) AS count FROM #table';
$res = $dbo->fetchAll( $sql );
// $res[0]->count contains the number of rows
I'm kind of a minimalist:
public function count()
{
$rows = $db->select()->from($db, 'count(*) as amt')->query()->fetchAll();
return($rows[0]['amt']);
}
Can be used generically on all tables.
Add count capability to your Zend_DB Object To count all table rows
public function count()
{
return (int) $this->_table->getAdapter()->fetchOne(
$this->_table->select()->from($this->_table, 'COUNT(id)')
);
}