Phalcon - get result of count in PHQL - php

I need to get number of rows from table as string.
I execute this code:
$phql = "SELECT COUNT(*) FROM Model WHERE id = $this->id";
$count = $this->getModelsManager()->createQuery($phql)->execute();
Now $count is Phalcon\Mvc\Model\Resultset\Complex object. To get a proper result I need to do something like that:
$count[0]->{0}
In my opinion this is awful. Is there any other way to get this result?

Few solutions:
1) Use simple queries:
$count = $this->db->fetchOne('SELECT COUNT(*) AS total FROM products');
2) Model aggregations
$count = Products::count(
"area = 'Testing'"
);
More info and methods: https://docs.phalconphp.com/ar/3.2/db-models in section Generating Calculations
3) If you insist of using executeQuery() you should add getFirst() in order to get only one result. Similar to PDO's fetchOne().
$phql = "SELECT COUNT(*) AS total FROM Models\Products";
$count = $this->modelsManager->executeQuery($phql)->getFirst();

Related

Timeout Error when doing Large select from loop

I have a simple php code below
$sql_items = "SELECT id FROM item_masterfile"; /* this query has 7000 rows */
$result_items = mysqli_query($con,$sql_items);
while ($row_items = mysqli_fetch_row($result_items)) {
$sql_qty = "SELECT qty FROM inventory WHERE id = ".$row_items[0];
/* rest of the code here */
}
}
this is working but due to a lot data my server cannot handle it and other queries took long to respond. how can I fix this? My target here is like batch select? to prevent clogged?
What I see in the process is a lot of select waiting to initiate.
How can I fix this?
try with batches using limit and offset like below
$offset = $i * 5000; // $i is run batch number .. 1, 2, 3 etc in the foreach() loop.
if ($i == 0) {
$offset = "";
}
$result_items="SELECT id FROM item_masterfile LIMIT 5000 OFFSET $offset;";
The code in your question shows that there is one_to_one or one_to_many relation between tables, so using pagination and join statement would resolve the problem.
Check below code hope to be helpful
$sql = "
SELECT im.id, i.qty
FROM item_masterfile AS im
JOIN inventory AS i ON
im.id = i.item_masterfile_id
LIMIT $offset, $limit
";
$result_items = mysqli_query($con,$sql);
you can set $offset and $limit dynamically in your code and go on ...
Instead of using the loop and providing id in there, you should collect all the ids in an array and then pass all of them to the query in one go using the IN operator.
Example: SELECT qty FROM inventory WHERE id IN (1,2,3,4,5). By doing this you can avoid loop and you code will not exit with timeout error.
OR
You can achieve the same using a subquery with your main query
Example: SELECT qty FROM inventory WHERE id IN (SELECT id FROM item_masterfile)
Try with follow step:
get result of first query and get id values like (1,2,3,4,...)..
and out side where clause execute second query with WHERE condition IN clause
Like
$sql_items = "SELECT id FROM item_masterfile"; /* this query has 7000 rows */
$result_items = mysqli_query($con,$sql_items);
while ($row_items = mysqli_fetch_row($result_items)) {
$ids[] = $row_items['id'];
}
$sql_qty = "SELECT qty FROM inventory WHERE id IN ".$ids;
/* rest of the code here */
}

PHP PDO pagination foreach

I'm trying to create a pagination for my PDO query. I cant figure it out. I've tried numerous google searches, but nothing that will work for me. [I probably didn't search hard enough. I'm not sure]
This is my code:
$sql2 = "SELECT * FROM comments WHERE shown = '1'ORDER BY ID DESC";
$stm2 = $dbh->prepare($sql2);
$stm2->execute();
$nodes2= $stm2->fetchAll();
foreach ($nodes2 as $n1) {
echo "text";
}
I want to be able to limit 10 comments per page, and use $_GET['PAGE'] for the page.
Something that I tried
$sql2 = "SELECT * FROM comments WHERE shown = '1'ORDER BY ID DESC";
$stm2 = $dbh->prepare($sql2);
$stm2->execute();
$nodes2= $stm2->fetchAll();
$page_of_pagination = 1;
$chunked = array_chunk($nodes2->get_items(), 10);
foreach ($chunked[$page_of_pagination] as $n1) {
echo "text";
}
If someone could help out, I appreciate it.
You need to limit the query that you are performing, getting all values from the database and then limiting the result to what you want is a bad design choice because it's highly inefficient.
You need to do this:
$page = (int)$_GET['PAGE']; // to prevent injection attacks or other issues
$rowsPerPage = 10;
$startLimit = ($page - 1) * $rowsPerPage; // -1 because you need to start from 0
$sql2 = "SELECT * FROM comments WHERE shown = '1' ORDER BY ID DESC LIMIT {$startLimit}, {$rowsPerPage}";
What LIMIT does:
The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants
More information here: http://dev.mysql.com/doc/refman/5.7/en/select.html
Then you can proceed getting the result and showing it.
Edit after comment:
To get all the pages for display you need to know how many pages are there so you need to do a count on that SELECT statement using the same filters, meaning:
SELECT COUNT(*) as count FROM comments WHERE shown = '1'
Store this count in a variable. To get the number of pages you divide the count by the number of rows per page you want to display and round up:
$totalNumberOfPages = ceil($count / $rowsPerPage);
and to display them:
foreach(range(1, $totalNumberOfPages) as $pageNumber) {
echo '' . $pageNumber . '';
}

how to use PHP function to get ranks for multiple columns in a table more efficent

I am trying to get single rank for a user for each stat "column" in the table. I am trying to do this as more efficiently because i know you can.
So I have a table called userstats. in that table i have 3 columns user_id, stat_1, stat_2, and stat_3. I want to me able to get the rank for each stat for the associated user_id. with my current code below i would have to duplicate the code 3x and change the column names to get my result. please look at the examples below. Thanks!
this is how i currently get the rank for the users
$rankstat1 = getUserRank($userid);
<code>
function getUserRank($userid){
$sql = "SELECT * FROM ".DB_USERSTATS." ORDER BY stat_1 DESC";
$result = mysql_query($sql);
$rows = '';
$data = array();
if (!empty($result))
$rows = mysql_num_rows($result);
else
$rows = '';
if (!empty($rows)){
while ($rows = mysql_fetch_assoc($result)){
$data[] = $rows;
}
}
$rank = 1;
foreach($data as $item){
if ($item['user_id'] == $userid){
return $rank;
}
++$rank;
}
return 1;
}
</code>
I believe there is a way for me to get what i need with something like this but i cant get it to work.
$rankstat1 = getUserRank($userid, 'stat_1'); $rankstat2 =
getUserRank($userid, 'stat_2'); $rankstat3 = getUserRank($userid,
'stat_3');
You can get all the stat ranks using one query without doing all the PHP looping and checking.
I have used PDO in this example because the value of the $userid variable needs to be used in the query, and the deprecated mysql database extension does not support prepared statements, which should be used to reduce the risk of SQL injection.
The function could be adapted to use the same query with mysqli, or even mysql if you must use it.
function getUserRanks($userid, $pdo) {
$sql = "SELECT
COUNT(DISTINCT s1.user_id) + 1 AS stat_1_rank,
COUNT(DISTINCT s2.user_id) + 1 AS stat_2_rank,
COUNT(DISTINCT s3.user_id) + 1 AS stat_3_rank
FROM user_stats f
LEFT JOIN user_stats s1 ON f.stat_1 < s1.stat_1
LEFT JOIN user_stats s2 ON f.stat_2 < s2.stat_2
LEFT JOIN user_stats s3 ON f.stat_3 < s3.stat_3
WHERE f.user_id = ?"
$stmt = $pdo->prepare($sql);
$stmt->bindValue(1, $userid);
$stmt->execute();
$ranks = $stmt->fetchObject();
return $ranks;
}
This should return an object with properties containing the ranks of the given user for each stat. An example of using this function:
$pdo = new PDO($dsn, $user, $pw);
$ranks = getUserRanks(3, $pdo); // get the stat ranks for user 3
echo $ranks->stat_2_rank; // show user 3's rank for stat 2
$sql = "SELECT user_id, stat_1, stat_2, stat_3 FROM ".DB_USERSTATS." ORDER BY stat_1 DESC";
Also, unless there is a reason you need ALL users results, limit your query with a WHERE clause so you're only getting the results you actually need.
Assuming you limit your sql query to just one user, this will get that user's stats.
foreach($data as $item){
$stat_1 = $item['stat_1'];
$stat_2 = $item['stat_2'];
$stat_3 = $item['stat_3'];
}
If you get more than one user's stats with your sql query, consider passing your $data array back to the calling function and loop through the array to match the users stats to particular user id's.

Subtracting Query Values

I am trying to make two queries providing $result and $result2. I would like to subtract the two results to create a total for the vote (negative vote being possible). Therefore on an empty query the result value would have to be zero.
My subtraction function isn't working. Does anyone know what I am doing wrong? I am getting no result.
Thanks in advance!
My code:
$result = mysql_query('SELECT COUNT(*) FROM comment_votes WHERE vote_com_writer_id = "'.$d['user_id'].'" AND vote_com_rank = "1"');
$positive_votes = mysql_result($result, 0);
$result2 = mysql_query('SELECT COUNT(*) FROM comment_votes WHERE vote_com_writer_id = "'.$d['user_id'].'" AND vote_com_rank = "2"');
$negative_votes = mysql_result($result2, 0);
list($vote) = $positive_votes - $negative_votes;
Start with the basics.
Confirm that your sql queries work by manually executing them against your database.
Confirm that $postive_votes and $negative_votes are what you expect with something like the following:
echo 'Positive Votes: '.$positive_votes.', Negative Votes: '.$negative_votes.
remove list($vote) as it is not being used correctly. The list function is intended for arrays not the results of subtraction. Replace that line with the following:
$total_votes = $positive_votes - $negative_votes;
echo 'Total Votes:'.$total_votes;
.

Zend Database get count

I have a query to count all rows in Db table.
$results = $db->fetchAll('select count(id) as total_keys, sum(if(used,1,0)) as used_keys from product_keys');
$this->_helper->flashMessenger->addMessage($results);
I want to get the total_keys and used_keys, but it doesn't seen to work.
$results = $db->fetchOne('select count(id) as total_keys, sum(if(used,1,0)) as used_keys from product_keys');
$this->_helper->flashMessenger->addMessage($results);

Categories