Manipulating MySQL database using php - php

Let's say that I want to perform 2 MySQL operations:
Operation 1:
SELECT * From Comments ORDER BY ID DESC
Operation 2:
SELECT * From Comments WHERE Date >'2012-05-01', ORDER BY ID ASC
Clearly, the second table is contained within the first; the specifics are just hypothetical. My question: Rather than perform 2 separate MySQL queries as done above, is it possible to obtain just the first, use it, then LATER manipulate it using php to obtain the second? In the example above, the php function would need to alter the order of the table and remove inapplicable rows, but again, it's just an example.
Why do I care?
Well, I'm trying to limit the number of MySQL connections to my server. Rather than have 5 separate queries that reference the same one master table, I'd prefer to have just 1, and use php to manipulate it 4 times so as to get the same final product.
Thanks!

No, you cannot "alter the table". When you query the database from PHP, you're not getting "the table" back as a result, you're just getting a result set back. What you can perfectly do is store this result in a PHP variable and use PHP code to further filter or sort that data:
$result = $pdo->query('SELECT * From Comments ORDER BY ID DESC')->fetchAll();
$result2 = array_filter($result, function (array $row) {
return strtotime($row['Date']) > strtotime('2012-05-01');
});
usort($result2, function (array $a, array $b) {
return $a['ID'] - $b['ID'];
});

It seems that can be done like this:
Launch first query
iterate backwords through results (you will programatically have ASC order instead of DESC)
2a. for each record check if "Date" meets your criteria

Related

How to get a single value from one record from a query into a field

In my system, I have plenty of instances of code like the following:
$value = mysqli_fetch_array(mysqli_query($con, "SELECT SUM(price) as total from items WHERE a=1 AND b=2"));
Then $value is used later in the code and has the total price calculated from the array
I'm trying to replicate this in a new piece of code as follows:
$recent_sale_id = mysqli_fetch_array(mysqli_query($con, "SELECT id as id FROM items where item_code='$item_code' and status='BULK-ITEM-SALE' order by sold_at DESC LIMIT 1"));
The query works when run directly against the database (of course replacing $item_code with the item code). But $recent_sale_id then just has the value 'Array'.
I'm wondering two things:
What am I doing wrong? My code seems to be exactly the same as the other code that works correctly.
Is there a simpler way to get a value from a query into a field, without using a function that seems like it will create an array? Is there a more suitable mysqli_fetch* function?
There's no way you could access $value as a number because it is also an array. In the first case you would need to use either $value[0] or $value['total'] to get the result; in the second either $recent_sale_id[0] or $recent_sale_id['id']. You can use either form because mysqli_fetch_array by default returns arrays indexed both by column number and column name.
Unfortunately the MySQLi interface does not have an equivalent to PDO's fetchColumn which allows you to directly fetch the value of a single column from a row in a result set.
If $recent_sale_id is returning a array in this case, that means it is of array type and in terms of getting data from mysql query often it comes in array format though you have added a limit 1.
One thing you can do to get the value is try $recent_sale_id[0] for the actual output.

Change the seed of RAND() function in PHP?

I accessed my table of database by a PHP script and I get continuous repeat results sometimes.
I ran this query:
$query ="SELECT Question,Answer1,Answer2 FROM MyTable ORDER BY RAND(UNIX_TIMESTAMP(NOW())) LIMIT 1";
Before of this query, I tried just with ORDER BY RAND(), but it gave me a lot of continuous repeat results, that's why I decided to use ORDER BY RAND(UNIX_TIMESTAMP(NOW())).
But this last one still give me continuous repeat results( but less).
Im going to write a example to explain what I mean when I said "continuous repeat results" :
Image that I have 100 rows in my table: ROW1,ROW2,ROW3,ROw4,ROW5...
well, when I call my script PHP 5 times continuosly I get 5 results:
-ROW2,ROW20,ROW20,ROW50,ROW66
I don't want same row continuously two times.
I would like it for example: -ROW2,ROW20,ROW50,ROW66,ROW20
I just want to fix it some easy way.
https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_rand
RAND() is not meant to be a perfect random generator. It is a fast way
to generate random numbers on demand that is portable between
platforms for the same MySQL version.
If you want 5 results, why not change the limit to 5 ? This will ensure that there are no duplicates
The other option is read all of the data out, and then use shuffle in php ?
http://php.net/manual/en/function.shuffle.php
Or select the max and use a random number generated from PHP
http://php.net/manual/en/function.mt-rand.php
This is not doable by just redefining the query. You need to change the logic of your PHP script.
If you want that the PHP script (and the query) returns exactly ONE row per execution, and you need a guarantee that repeated executions of the PHP scrips yield different rows, then you need to store the previous result somewhere, and use the previous result in the WHERE condition of the query.
So your PHP script becomes something like (pseudocode):
$previousId = ...; // Load the ID of the row fetched by the previous execution
$query = "SELECT Question,Answer1,Answer2
FROM MyTable
WHERE id <> ?
ORDER BY RAND(UNIX_TIMESTAMP(NOW()))
LIMIT 1";
// Execute $query, using the $previousId bound parameter value
$newId = ...; // get the ID of the fetched row.
// Save $newId for the next execution.
You may use all kinds of storages for saving/loading the ID of the fetched rows. The easiest is probably to use a special table with a single row in the same database for this purpose.
Note that you may still get repeated sequential rows if you call your PHP script many times in parallel. Not sure if it matters in your case.
If it does, you may use locks or database transactions to fix this as well.

Reordering MySQL

I have probably a very simple question.
I have a MySQL database called "alldata", which contains various variables. The first column called LogDateTime contains date and time. Now the thing is that I want the db to be sorted from the oldest to the newest - in other words by column 1.
I know how to do a MySQL query using ORDER BY Logdatetime etc. But what I would like to do is to reorder tha data in the actual database and save it ordered. Right now there are some dates a bit messed up. Then I would not have to use the ORDER BY statement in all my queries because the database would already be sorted.
Could anyone please just give me the SQL command I should use to reorder the entire database?
You cannot setup a relational database table to return results ordered by a specific column of your choosing. You need to use ORDER BY. You could work around this by using views.
The view definition would include an ORDER BY. You could select from the view and it would show results in your desired order.
CREATE OR REPLACE VIEW `mytable_view` AS SELECT * FROM `my_table` ORDER BY `my_date_column`
Then you can select the data:
SELECT * FROM `mytable_view`
Results are shown in desired order.

how to make mysql queries in php run quicker

i am running queries on a table that has thousands of rows:
$sql="select * from call_history where extension_number = '0536*002' and flow = 'in' and DATE(initiated) = '".date("Y-m-d")."' ";
and its taking forever to return results.
The SQL itself is
select *
from call_history
where extension_number = '0536*002'
and flow = 'in'
and DATE(initiated) = 'dateFromYourPHPcode'
is there any way to make it run faster? should i put the where DATE(initiated) = '".date("Y-m-d")."' before the extension_number where clause?
or should i select all rows where DATE(initiated) = '".date("Y-m-d")."' and put that in a while loop then run all my other queries (where extension_number = ...) whthin the while loop?
Here are some suggestions:
1) Replace SELECT * by the only fields you want.
2) Add indexing on the table fields you want as output.
3) Avoid running queries in loops. This causes multiple requests to SQL server.
4) Fetch all the data at once.
5) Apply LIMIT tag as and when required. Don't select all the records.
6) Fire two different queries: one for counting total number of records and other for fetching number of records per page (e.g. 10, 20, 50, etc...)
7) If applicable, create Database Views and get data from them instead of tables.
Thanks
The order of clauses under WHERE is irrelevant to optimization.
Pro-tip, also suggested by somebody else: Never use SELECT * in a query in a program
unless you have a good reason to do so. "I don't feel like writing out the names of the columns I need" isn't a good reason. Always enumerate the columns you need. MySQL and other database systems can often optimize things in surprising ways when the list of data columns you need is available.
Your query contains this selection criterion.
AND DATE(initiated) = 'dateFromYourPHPcode'
Notice that this search criterion takes the form
FUNCTION(column) = value
This form of search defeats the use of any index on that column. Your initiated column has a TIMESTAMP data type. Try this instead:
AND initiated >= 'dateFromYourPHPcode'
AND initiated < 'dateFromYourPHPcode' + INTERVAL 1 DAY
This will find all the initiated items in the particular day. And, because it doesn't use a function on the column value it can use an index range scan to do that, which performs well. It may, or may not, also help without an index. It's worth a try.
I suspect your ideal index for this particular search would created by
ALTER TABLE call_history
ADD INDEX flowExtInit (flow, extension_number, initiated)
You should ask the administrator of the database to add this index if your query needs good performance.
You should add index to your table. This way MySql will fetch faster. I have not tested but command should be like this:
ALTER TABLE `call_history ` ADD INDEX `callhistory` (`extension_number`,`flow`,`extension_number`,`DATE(initiated)`);

(php) mysql_fetch_array - How does it know which row to access

I'm learning currently php/mysql and I'm confused about this bit.
After some heads scratching I have figured out that mysql_fetch_array remembers which row it last accessed and accesses the next one. (I was originally trying to work out how the code was communicating this to it in example code)
so for database:
parent | job
-------+-------------
mom | receptionist
-------+-------------
dad | taxi driver
the code
mysql_fetch_array($result)[job]
returns 'receptionist' the first time and 'taxi driver' the second.
Where/how is it keeping track of this?
What happens if I don't want to access them in order?
thanks
internal implementation in PHP. Don't try to figure it out ;)
if you want a different order, then specify it in your database query.
Where/how is it keeping track of this?
The mySQL server has an internal result pointer. In some databases / wrappers / libraries you can rewind that pointer, but as far as I know, this is not possible in the mysql_* library of functions.
What happens if I don't want to access them in order?
You have to access them in some order. The only alternative to that is to fetch all rows into an array: Then you can access each row randomly.
If you want to change the order of records, do that in the query using the ORDER clause.
Some database wrappers like PDO have a fetchAll() method that does exactly that. For large result sets, this can be memory intensive and break the script's memory limit, which is why it's usually not done this way.
There is another way to attack this question.
If you want to know how YOU TOO can make functions that do what this one does. Here is how:
<?php
function count_off()
{
static $count = 1;
echo $count++;
}
count_off();
count_off();
count_off();
count_off();
count_off();
?>
the above will output 12345
I should mention. You shouldn't do this without a very good reason. It is SUPER hard to trace when debugging.
If you want to access them in a different order, use an ORDER BY clause in your SQL to change the order that the results are retrieved from the database.
The result of mysql_fetch_array is always the next result/row of the query (first the first row off course)
Intern it will keep a pointer how for it has fetched.
If you want to get them in an alternate order, you have to define it in the query.
Like said the result will always be in the order specified by the query (implicit or explicit)
If you wrote typical looking code like this:
$result = mysql_query("SELECT parent, job FROM table");
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
echo $row['parent'] . ' - ' . $row['job'];
}
Each time mysql_fetch_array() is called, if there is another row in the result, it will return the row as an associative array into the $row variable. Otherwise, it will return false, and the execution of the while loop will end.
Also, because you didn't specify an ORDER BY clause, it defaults to returning rows in the order they were inserted into the table.
The mysql_fetch_array() function grabs one row from the database, in the order that MySQL returns it from the query you gave.
To obtain all the rows, you can put the function in a loop.
while($row = mysql_fetch_array($result)) {
echo $row["job"];
}
This will output:
receptionist
taxi driver
You can change the order by using the sql term order by, which can alphabetically or numerically order your results by a certain column
select * from parent order by job
The above query will order the results alphabetically by the parent job field (results closer to A will come first in the mysql_fetch_*

Categories