How to get random row from MYSQL and how to write it in active records? - mysql

This is my query
"SELECT * FROM package_info ORDER BY RAND() LIMIT 0,3;"
I try to write it in active records like this.
$this->db->select('*');
$this->db->from('package_info');
$this->db->order_by("id", "random");
$this->db->limit(0, 3);
$result = $this->db->get();
But it is not work. How to write this in active record?

Use Below code it will work fine -
$this->db->select('*');
$this->db->from('package_info');
$this->db->order_by("id", "random");
$this->db->limit(3, 0);
$result = $this->db->get()->result();
// shows last executed query
echo $this->db->last_query();
// shows data fetched
echo "<pre>";
print_r( $result );
echo "</pre>";
You can visit on this link to view how queries are used in Codeigniter.
https://www.codeigniter.com/userguide2/database/active_record.html

CodeIgniter does not mandate that you provide 2 arguments for most Query Builder statements, you can do a whole WHERE by doing ->where('1=1') and its perfectly fine.
I'm surprised how many people don't understand method chaining, but I'll show it in my example it is just nicer...
$result = $this->db->select('*')
->from('package_info')
->order_by('rand()')
->limit(0, 3)
>get();
As per above, if you don't have 2 parameters in your original query, dont feel compelled to add two.
Another thing you can do with basic queries like these, is omit the from('package_info') entirely and stick the table name in the ->get('package_info')
If you cant be bothered with query builder you don't need to use it either. I don't for some things (you cannot use UNION with them for one). In this case just use
$result = $this->db->query("SELECT * FROM package_info ORDER BY RAND() LIMIT 0,3;");

Related

Code Igniter - not showing the entry I need

I have the following code to get one line for each MAC with the LATEST state. The problem I have is that I get one line but not with the latest state but rather with the earliest.
function get_active_devices($min_duration, $max_duration)
{
//get all active devices DESC order
$this->db->distinct();
$this->db->group_by('mac');
$this->db->order_by("id", "desc");
$this->db->select('data.mac, state, time, iot_bo.notified, iot_bo.op_state, iot_bo.Name');
$this->db->where('time >', time()-$max_duration);
$this->db->where('time <', time()-$min_duration);
$this->db->join('iot_bo', 'iot_bo.mac = data.mac');
$this->db->where('iot_bo.op_state', '1');
$query = $this->db->get();
return $query;
}
Have you tried the query without the distinct and groupBy first? May be the result you want isn't in the total result set to begin with. Because there doesn't seem to be anything wrong with your use of db methods as it is.

how to use getNumRows() in Joomla after a second query

I am developing a php script within the Joomla environment which queries the same table / database twice. Each time I need to know whether any matches are found.
It seemed that the best way would be to use the getNumRows(). The Joomla documentation is very specific on its use:
Miscellaneous Result Set Methods getNumRows()
getNumRows() will return the number of result rows found by the last
query and waiting to be read. To get a result from getNumRows() you
have to run it after the query and before you have retrieved any
results.
I follow this in my script. At the first query there is no problem, but the second query always throws up a warning - most likely because the getNumRows() call for the second time is after the retrieving results from the first query - which does not comply with the Joomla requirement.
Any ideas how to solve? Many thanks!
The part of my script in question reads:
$db = JFactory::getDBO();
$query = "SELECT * FROM #__art_mobiles WHERE user_agent_header='$ua'";
$db->setQuery($query);
$rowsAG = $db->getNumRows();
$replyAG = $db->loadRow();
if ($rowsAG == 0) {
//if no match check www.handsetdetection.com
//see https://www.handsetdetection.com/properties/vendormodel for current list of models in database together with headers
echo "not in local database - try external<br/>";
$prod = '';
if ($hd3->siteDetect()) {
$replyHD = $hd3->getReply();
$man = $replyHD['hd_specs']['general_vendor'];
$dev = $replyHD['hd_specs']['general_model'];
$os = $replyHD['hd_specs']['general_platform'];
echo "found in handsetdetection.com database<br/>";
//check for provisional match in local database
$query = "SELECT * FROM #__art_mobiles WHERE manufacturer='$man' AND device='$dev'";
$db->setQuery($query);
$rowsAGprov = $db->getNumRows();
$replyAGprov = $db->loadRow();
if ($rowsAGprov == 0) { **[ETC]**
I think this could be an issue with using $db->loadRow(); as getNumRows relies on an executed query.
For example you could try:
$db = JFactory::getDBO();
$query = "SELECT * FROM #__art_mobiles WHERE user_agent_header='$ua'";
$db->setQuery($query);
$replyAG = $db->query();
$rowsAG = $db->getNumRows();
And:
$query = "SELECT * FROM #__art_mobiles WHERE manufacturer='$man' AND device='$dev'";
$db->setQuery($query);
$replyAGprov = $db->query();
$rowsAGprov = $db->getNumRows();
Though I am not sure what/if the difference will be between the results returned from query and loadRow. It would be worth experimenting and seeing if this works.
Alternately, if you are only using getNumRows to see if a record exists, you could do some kind of check on your $replyAG variable instead. It again might be worth experimenting to see what loadRow returns if there are no results.
You need to add the following code before you write the the query:
$query = $db->getQuery(true);
You need to use
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select($db->qn(array('id')))
->from($db->qn('#__social_notifications'))
->where($db->qn('status') . ' = ' . $db->q(0));
$db->setQuery($query);
$db->execute();
$resultData = $db->getNumRows();

Narrow search results from mysql database keywords

I have a large database containing part numbers for a filter company. Several of the products have similar years and model numbers. I have a php script that is searching a text keyword section for each part.
So for a 1997-1999 Honda Crf 250 090987 19.95 the keywords are:
1997 1998 1999 honda crf 250 090987
I got the code from a tutorial and it's written to search the keywords section for everything separated by a space. The problem is that a lot of the listings have honda or similar year spreads.
I need to figure out how to alter the php to narrow the results so if someone types "1997 honda", all of the hondas and '97s don't show up but only ones that are 1997 hondas.
I'm new to php and I've looked all around and can't figure it out. Any help will be thoroughly appreciated.
here's the php:
$keywords = $_GET['keywords'];
$terms = explode(" ", $keywords);
$query = "SELECT * FROM search WHERE ";
foreach ($terms as $each){
$i++;
if ($i == 1)
$query .= "keywords LIKE '%$each%' ";
else
$query .= "OR keywords LIKE '%$each%' ";
}
// connect
mysql_connect("localhost", "root", "root");
mysql_select_db("catalog");
$query = mysql_query($query);
$numrows = mysql_num_rows($query);
if ($numrows > 0){
while ($row = mysql_fetch_assoc($query)){
$id = $row['id'];
$year = $row['year'];
$manufacturer = $row['manufacturer'];
$product = $row['product'];
$partnumber = $row['partnumber'];
$price = $row['price'];
echo "<div id=\"results\">
<div class=\"words\">$year</div><div class=\"words\">$manufacturer</div><div class=\"words\">$product</div><div class=\"words\">$partnumber</div>$price<br /></div>";
}
}
else
echo "<div class=\"no_results\"><center>No results found for \"<b>$keywords</b>\"</center></div>";
// disconnect
mysql_close();
?>
Interesting problem.
I thought of 2 approaches:
(1) if you have control over the database structure, you could SELECT WHERE (make = 'Honda' AND Year IN (1997,1998,1999)) AND the "like" stuff you already have (without the make/year). But you would need to separate out the model years and make into separate fields.
(2) otherwise, if we can assume the input is always "year(s) make [other keywords], we could do what izuriel suggested while I was typing this, just "AND 'keywords = '1997' AND keywords = 'honda' AND (our existing list of "like" clauses)".
that way you'd get only 1997 Hondas that have any or all of the other keywords.
Use AND in the query instead of OR to enforce that all keywords must match, otherwise one keyword match will return a result always. Outside of that, you'll have to do some Relevance work in code which might slow down the application.
I recommend you to use one symbol percentage at the end of the word and you and instead of or and you limit in your query if the database is large

MySql: Best way to run high number of search queries on a table

I have two tables, one is static database that i need to search in, the other is dynamic that i will be using to search the first database. Right now i have two separate queries. First on page load, values from second table are passed to first one as search term, and i am "capturing" the search result using cURL. This is very inefficient and probably really wrong way to do it, so i need help in fixing this issue. Currently page (html, front-end) takes 40 seconds to load.
Possible solutions: Turn it into function, but still makes so many calls out. Load table into memory and then run queries and unload cache once done. Use regexp to help speed up query? Possible join? But i am a noob so i can only imagine...
Search script:
require 'mysqlconnect.php';
$id = NULL;
if(isset($_GET['n'])) { $id = mysql_real_escape_string($_GET['n']); }
if(isset($_POST['n'])) { $id = mysql_real_escape_string($_POST['n']); }
if(!empty($id)){
$getdata = "SELECT id, first_name, last_name, published_name,
department, telephone FROM $table WHERE id = '$id' LIMIT 1";
$result = mysql_query($getdata) or die(mysql_error());
$num_rows = mysql_num_rows($result);
while($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
echo <<<PRINTALL
{$row[id]}~~::~~{$row[first_name]}~~::~~{$row[last_name]}~~::~~{$row[p_name]}~~::~~{$row[dept]}~~::~~{$row[ph]}
PRINTALL;
}
}
HTML Page Script:
require 'mysqlconnect.php';
function get_data($url)
{
$ch = curl_init();
$timeout = 5;
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
$getdata = "SELECT * FROM $table WHERE $table.mid != '1'ORDER BY $table.$sortbyme $o LIMIT $offset, $rowsPerPage";
$result = mysql_query($getdata) or die(mysql_error());
while($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
$idurl = 'http://mydomain.com/dir/file.php?n='.$row['id'].'';
$p_arr = explode('~~::~~',get_data($idurl));
$p_str = implode(' ',$p_arr);
//Use p_srt and p_arr if exists, otherwise just output rest of the
//html code with second table values
}
As you can see, second table may or may not have valid id, hence no results but second table is quiet large, and all in all, i am reading and outputting 15k+ table cells. And as you can probably see from the code, i have tried paging but that solution doesn't fit my needs. I have to have all of the data on client side in single html page. So please advice.
Thanks!
EDIT
First table:
id_row id first_name last_name dept telephone
1 aaa12345 joe smith ANS 800 555 5555
2 bbb67890 sarah brown ITL 800 848 8848
Second_table:
id_row type model har status id date
1 ATX Hybrion 88-85-5d-id-ss y aaa12345 2011/08/12
2 BTX Savin none n aaa12345 2010/04/05
3 Full Hp 44-55-sd-qw-54 y ashley a 2011/07/25
4 ATX Delin none _ smith bon 2011/04/05
So the second table is the one that gets read and displayed, first is read and info displayed if ID is positive match. ID is only unique in the first one, second one has multi format input so it could or could not be ID as well as could be duplicate ID. Hope this gives better understanding of what i need. Thanks again!
A few things:
Curl is completely unnecessary here.
Order by will slow down your queries considerably.
I'd throw in an if is_numeric check on the ID.
Why are you using while and mysql_num_rows when you're limiting to 1 in the query?
Where are $table and these other things being set?
There is code missing.
If you give us the data structure for the two tables in question we can help you with the queries, but the way you have this set up now, I'm surprised its even working at all.
What you're doing is, for each row in $table where mid!=1 you're executing a curl call to a 2nd page which takes the ID and queries again. This is really really bad, and much more convoluted than it needs to be. Lets see your table structures.
Basically you can do:
select first_name, last_name, published_name, department, telephone FROM $table1, $table2 WHERE $table1.id = $table2.id and $table2.mid != 1;
Get rid of the curl, get rid of the exploding/imploding.

PHP Array Duplicates

my first post here and hoping someone can help. I am querying a table in a mySQL DB, and obviously getting the results. However, the table is used to store multiple entry by one user for the purpose of user contacts.
What I would like to do is display each user individually, and count the number of contacts each user has. I had a look at the post "How to detect duplicate posts in PHP array, which helped a bit, but I am still stuck.
Please see my code for the query below, I have left out the array duplicate part as it is a pretty mess at the moment.
<?php
$result = mysql_query("SELECT * FROM vines");
while($row = mysql_fetch_array($result)) {
$results=$row['vinename'];
echo $results;
echo "<br />";
}
?>
This result returns the below, obviously these are records from the vinename coloumn.
Marks Vine<br />
Marks Vine<br />
Marks Vine<br />
Tasch Vine<br />
Tasch Vine<br />
Regards
Mark Loxton
Hi there, my first post here and hoping someone can help. I am querying a table in a mySQL DB, and obviously getting the results. However, the table is used to store multiple entry by one user for the purpose of user contacts.
You can do this in the query itself a lot more easily than in the PHP code afterwards.
SELECT name, COUNT(id) AS count FROM vines GROUP BY name
Just change the SQL Query to
SELECT vinename, COUNT(vinename) as counter FROM vines GROUP BY vinename
and then do
echo $row['vinename']." #".$row['counter']."<br />";
I would run two types queries...
1) Select each UNIQUE user from vines.
2) For each user in that set, run a second COUNT query against that user's id in the table "vines".
I hope that helps.
You can create a separate array to store records you've already output there.
<?php
$result = mysql_query("SELECT * FROM vines");
$duplicates = array(); ## store duplcated names here
while($row = mysql_fetch_array($result)) {
$results = $row['vinename'];
if (!array_key_exists($results, $duplicates)) {
echo $results;
echo "<br />";
$duplicates[$results] = 1; ## mark that we've already output this records
}
}
?>
You can try, change your query to use count and group of SQL.
Somoe thing like
$result = mysql_query("SELECT count(*) as total,name FROM vines GROUP by name");
firstly thank you everyone for such awesome input. I seriously did not expect such a quick response. I am seriously grateful.
I used the recommendation from Jitter. I have pretty much been going through so many variations of the above code today, but just needed that missing piece.
Thanks, everyone. Below is what the final code looks like for anyone else who has the same problem in the future.
<?php
$result = mysql_query("SELECT vinename, COUNT(vinename) as counter FROM vines GROUP BY vinename ORDER BY counter DESC LIMIT 0, 3");
while($vinerow = mysql_fetch_array($result))
echo $vinerow['vinename']." has ".$vinerow['counter']." tomatos."."<br />";
?>
change your query to:
SELECT distinct * FROM vines