Reputation: 9719
I have a table which looks like this:
ID | name | phone_number | date 1 | bob | 4567 | 1/1/2011 2 | bob | 8912 | 1/1/2010 3 | bob | 1234 | 1/1/2010 4 | bob | 1234 | 1/1/2014 5 | bow | 4567 | 1/1/2014
I am creating an auto suggest so as a user types a name it will pick up previous names and phone numbers. As people can change their number, I want to order the results and display a count of the numbers based on the most popular phone number. As a second sort it should be based on the name and a final sort on the date it was added (newest first).
So if someone types 'bo' it should return:
bob 1234 (2) - Because it is alphabetically highest plus has the most phone numbers. bob 4567 (1) - Because it is alphabetically highest and its last entry is newer. bob 8912 (1) - Because it is alphabetically highest and its last entry was older. bow 4567 (1) - Because it is alphabetically lower.
Normally I would use the Zend methods for example:
public function getAllNames($part)
{
$select = $this->select();
$select->where('name LIKE ?', '%'.$part.'%')
->order('name');
return $this->fetchAll($select)->toArray();
}
But I am stuck on how to count the entries for phone numbers and then perform the three orders.
OR is it better to just get all the entries and use PHP to process the results and order them accordingly?
Upvotes: 1
Views: 462
Reputation: 9719
Here is the answer I have actually used thanks to user3511578. As in the comments, I don't have the expression module in my zend library, so I did it like this:
Just in case it helps anyone in the future:
public function getAllNames($part)
{
$select = $this->select();
$select->from($this->_name, array('name', 'phone_number', 'count'=>'COUNT(phone_number)'))
->where('name LIKE ?', '%'.$part.'%')
->group('name')
->group('number')
->order('name')
->order('count DESC')
->order('date desc');
return $this->fetchAll($select)->toArray();
}
Upvotes: 1
Reputation: 33935
If I understand correctly...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(12) NOT NULL
,phone_number VARCHAR(12) NOT NULL
,date DATE NOT NULL
);
INSERT INTO my_table VALUES
(1 ,'bob','4567','2011-01-01'),
(2 ,'bob','8912','2010-01-01'),
(3 ,'bob','1234','2010-01-01'),
(4 ,'bob','1234','2014-01-01'),
(5 ,'bow','4567','2014-01-01');
SELECT x.*
, y.total
FROM my_table x
JOIN
( SELECT name
, phone_number
, MAX(date) n_date
, COUNT(*) total
FROM my_table
WHERE name LIKE 'bo%'
GROUP
BY name
, phone_number
) y
ON y.name = x.name
AND y.phone_number = x.phone_number
AND y.n_date = x.date
ORDER
BY x.name
, y.total DESC
, x.date DESC;
+----+------+--------------+------------+-------+
| ID | name | phone_number | date | total |
+----+------+--------------+------------+-------+
| 4 | bob | 1234 | 2014-01-01 | 2 |
| 1 | bob | 4567 | 2011-01-01 | 1 |
| 2 | bob | 8912 | 2010-01-01 | 1 |
| 5 | bow | 4567 | 2014-01-01 | 1 |
+----+------+--------------+------------+-------+
Upvotes: 0
Reputation: 1444
What about following?
public function getAllNames($part)
{
$select = $this->select();
$select->where('name LIKE ?', '%'.$part.'%')
->order('name')
->order(new \Zend\Db\Sql\Expression('LENGTH(phone_number)'))
->order('date desc');
return $this->fetchAll($select)->toArray();
}
UPDATED ANSWER
public function getAllNames($part)
{
$select = $this->select();
$select->where('name LIKE ?', '%'.$part.'%')
->group('name')
->group('phone_number')
->order('name')
->order(new \Zend\Db\Sql\Expression('count(phone_number) DESC'))
->order(new \Zend\Db\Sql\Expression('max(date) DESC'));
return $this->fetchAll($select)->toArray();
}
Another UPDATE: using max(date) is not necessary
public function getAllNames($part)
{
$select = $this->select();
$select->where('name LIKE ?', '%'.$part.'%')
->group('name')
->group('phone_number')
->order('name')
->order(new \Zend\Db\Sql\Expression('count(phone_number) DESC'))
->order('date DESC');
return $this->fetchAll($select)->toArray();
}
Upvotes: 1