Filtering SQL Queries Using PHP - php

I have been searching for a while on a way to select certain columns (fields) in SQL.
What I am trying to do is this... Lets say I have a table with 200 columns of data. I want to select an entire row but only the last 197 columns of data. Leaving out the first 3 columns that have dates and ID's.
It would be very time consuming to type out the 197 field names I wanted the data from. There has to be some easier way of doing it.
Any help or suggestions to point me in the correct direction?

If you are using MySQL, try something like this:
<?php
$query = "
SHOW COLUMNS FROM `Table`
WHERE `Field` NOT LIKE 'rowtoignore1'
AND `Field` NOT LIKE 'rowtoignore2'
AND `Field` NOT LIKE 'rowtoignore3'
";
$r = mysql_query($query) or die(mysql_error());
$queryfields = "";
while($f = mysql_fetch_assoc($r)) {
$queryfields .= "`{$f['Field']}`,";
}
$queryfields = substr($queryfields,0,strlen($queryfields)-1);
$query = "SELECT {$queryfields} FROM `Table` WHERE xyz";
?>

If you're using MySQL you can query the schema to get a column name by index, so you could use an iterative PHP routine to build your query, but it would require 197 select statements before you could run the one you really want. Messy and inefficient.
It seems simpler to do a SELECT * and then ignore the first three columns. If you use mysql_fetch_assoc() you can get the columns you want easily. Take a look at:
http://php.net/manual/en/function.mysql-fetch-array.php

If i am doing this task, i won't exclude the first 3 columns . If the 3 columns contains lengthy text / blob , then you could avoid, else better fetch those 200 columns .
Using this function mysql_list_fields() fetch fields corresponding to a table , and customize the select query to include required fields

Related

How can I count entries in mySQL database faster?

I am counting the entries in my SQL database:
$sql = "SELECT * FROM files WHERE id = ?";
$q = $pdo->prepare($sql);
$q->execute([$id]);
$rowCount =$q->rowCount();
The result of $rowCount is 500000.
But to output this single number takes 5 seconds! Is it possible to get this result faster?
Use the COUNT() function https://dev.mysql.com/doc/refman/8.0/en/counting-rows.html:
$sql = "SELECT COUNT(*) FROM files WHERE id = ?";
Also ensure that 'id' is an indexed column:
https://dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html
Replace * with a field(use auto-increment id) - This will reduce the time a bit.
Index that field. - If you use indexed field the query performance will increase.
SELECT * ..., then counting in PHP, requires shoveling all columns of all rows back to PHP. That's a lot of effort for very little gain.
SELECT COUNT(col) ... does the counting in by MySQL, but it must check for whether col is NULL. And it needs to get at the value of col for every row.
SELECT COUNT(*) ... counts the rows by whatever way is most efficient. This involves looking for the 'smallest' index (or the whole table, if no secondary indexes), and counting through it.
You must learn about INDEXes to get anywhere in databases! This is only one minor use for them.

Addition from MySQL query

I am trying to add this:
if (question_counter==10){
$query3 = "SELECT answer_points WHERE participation_id=".$participation_id;
$dbc->query($query3)
}
This is supposed to get all the answer_points where the participation_id = "something". This happens when I receive in my PHP function that question_counter has reached 10
I now want to perform an addition between all the results I receive in my query above so that I can find out a total score and store it as a variable.
How would I go about doing this efficiently?
I thought about writing queries for each answer where I get the participation_id and the question_counter to write the query, store each row result in a separate variable and add all those together. I think this is an overkill and dumb since I will have to write 10 queries to get each row's result.
Anyway this is my Table
You can use MySQL's SUM function.
SELECT SUM(columnName) AS totalScore FROM tableName WHERE id = 34;
Your query is not correct.
$query3 = "SELECT answer_points FROM table_name WHERE participation_id=".$participation_id;
^^^^^^^^^^^^^^^
from and table name
You have forgot from and table name in the query.
To get the sum of the column you need to use the SUM function of mysql.
Here is tutorial of SUM function in mysql.
You have to write query using SUM function
$query3 = "SELECT SUM(answer_points) AS answer_points
FROM TABLE_NAME
WHERE participation_id=".$participation_id;

Autosuggestion works too slow

I have more than 100,000 records in my books table, my database is MySQL. I am creating an autosuggestion using PHP. It is working but it is slow. I think it is because of bulk data. Is there any solution for searching data in effective manner and how can we improve speed of that searching process?
Here is my code:
<?php
$search=$_REQUET['searc'];
$qry="select book_name from books where book_name like '%$search'";
$result=mysql_query($qry);
echo "<ul>";
while($rows=mysql_fetch_array($result))
{
echo "<li>".$rows['book_name']."<li>;
}
echo "</ul>";
?>
apply indexing or you can use fulltext indexing and search
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
$search = mysql_real_escape_string($_REQUEST['searc']);
$qry = "select book_name from books where book_name like '$search%' LIMIT 10";
and an ordinary index will solve the problem... for a while
Change your query as follows. It will fetch only first 30 items. Now the speed will increase. Also You can index your table correctly for speeding
$qry="select book_name from books where book_name like '%$search' LIMIT 0 , 30";
Try executing the following code in MYSQL:
ALTER TABLE `books` ADD INDEX `book_name` (`book_name`):
This will add an index to the table, this should speed up the search.
You are searching on the suffix of the column. Indexes work with the prefix so this query requires a full table scan. To fix this you can add a column that has the original in reverse, index it, and use it for searching:
alter table books add book_name_reverse tinytext;
update books set book_name_reverse = reverse(book_name);
alter table books add index(book_name_reverse);
After that you can search efficiently with:
$search_rev=strrev($_REQUET['searc']);
$qry="select book_name from books where book_name_reverse like '$search_rev%'";
But please use PDO or MySQLi prepared statements instead of doing this. Splicing user-submitted values into queries like this makes a classic SQL injection vulnerability.

select and update mysql same query

I'm running a query to select an array of id's from one table, so that I can update another table with the data from the resulting dataset.
//db query result
$query = "SELECT image_id FROM jos_jxgallery_images ORDER BY jos_jxgallery_images.image_id DESC LIMIT 25";
$query_execute = mysql_query($query);
mysql_close($db_config);
while ($items = mysql_fetch_array($query_execute)) {
echo $items['image_id'];
echo '<br/>';
}
I think I need to do it in the while loop, I just have the echo there to see what's in items variable. That works ok. I think the thing to do is in the while loop..I'd like to replace the 'echoing' with an actual update SET query for my other table. Something like...
while ($items = mysql_fetch_array($query_execute)) {
$q = "UPDATE jx_gallery_images_ratings SET image_id ='".$items."";
mysql_query($q);
But the new table has no data. Is there just a better way to write this...maybe even as one query or something? Any help is appreciated.
EDIT: I should explain a little better. The table is empty, and I could go ahead and use an insert from one table to another just to get the id's there. However, after that...in a way it is somewhat a 'temp' table. But not really. Whatever ordering of image_id's I have created in my SELECT query from my first table (There are other rows to sort by other than image_id, like 'hits', for example)...so the second table needs to be updated with the same ordering of image_id's. Probably be running this several little snippet several times with a cron job. So, yeah, I'm trying to update the second table with the ordering of the SELECT query of the first table and just put the id's in my second table, again...according to the order of the first SELECT query.
If the table is empty, you should do an insert. You can do it in a single query like this:
INSERT INTO jx_gallery_images_ratings (image_id)
SELECT image_id FROM jos_jxgallery_images ORDER BY jos_jxgallery_images.image_id DESC LIMIT 25
Note that you probably wouldn't really need the ORDER BY, adn you could do it for all images at once by removing the LIMIT
Something like:
UPDATE tbl_updateme SET row_to_update = (SELECT row_you_need from tbl_target WHERE tbl_updateme.comparison_row = tbl_target.comparison_row)
INSERT INTO jx_gallery_images_ratings (image_id) (SELECT image_id FROM jos_jxgallery_images ORDER BY jos_jxgallery_images.image_id DESC LIMIT 25)
Or
Easy way is create trigger that updates table after selection with Dynamic SQL

Select on empty table but still get column names

I want to do a SELECT on an empty table, but i still want to get a single record back with all the column names. I know there are other ways to get the column names from a table, but i want to know if it's possible with some sort of SELECT query.
I know this one works when i run it directly in MySQL:
SELECT * FROM cf_pagetree_elements WHERE 1=0;
But i'm using PHP + PDO (FETCH_CLASS). This just gives me an empty object back instead of an row with all the column names (with empty values). So for some reason that query doesn't work with PDO FETCH_CLASS.
$stmt = $this->db->prepare ( $sql );
$stmt->execute ( $bindings );
$result = $stmt->fetchAll ( \PDO::FETCH_CLASS, $class );
print_r($result); // Empty object... I need an object with column names
Anyone any idea if there's another method that i can try?
Adding on to what w00 answered, there's a solution that doesn't even need a dummy table
SELECT tbl.*
FROM (SELECT 1) AS ignore_me
LEFT JOIN your_table AS tbl
ON 1 = 1
LIMIT 1
In MySQL you can change WHERE 1 = 1 to just WHERE 1
To the other answers who posted about SHOW COLUMNS and the information scheme.
The OP clearly said: "I know there are other ways to get the column names from a table, but i want to know if it's possible with some sort of SELECT query."
Learn to read.
Anyway, to answer your question; No you can't. You cannot select a row from an empty table. Not even a row with empty values, from an empty table.
There is however a trick you can apply to do this.
Create an additional table called 'dummy' with just one column and one row in it:
Table: dummy
dummy_id: 1
That's all. Now you can do a select statement like this:
SELECT * FROM dummy LEFT OUTER JOIN your_table ON 1=1
This will always return one row. It does however contain the 'dummy_id' column too. You can however just ignore that ofcourse and do with the (empty) data what ever you like.
So again, this is just a trick to do it with a SELECT statement. There's no default way to get this done.
SHOW COLUMNS FROM cf_pagetree_elements;
This will give a result set explaining the table structure. You can quite easily parse the result with PHP.
Another method is to query the infomrmation schema table:
SELECT column_name FROM information_schema.columns WHERE table_name='cf_pagetree_elements';
Not really recommended though!
You could try:
SELECT * FROM information_schema.columns
WHERE table_name = "cf_pagetree_elements"
Not sure about your specific PHP+PDO approach (there may be complications), but that's the standard way to fetch column headings (field names).
this will list the columns of ANY query for PDO drivers that support getColumMeta. I am using this with SQL server and works fine even on very complex queries with aliased tables, sub-queries and unions. Gives me columns even when results are zero
<?php
// just an example of an empty query.
$query =$PDOdb->query("SELECT * from something where 1=0; ");
for ($i=0; $i<$query->columnCount(); $i++) {
echo $query->getColumnMeta($i)['name']."<br />";
}
?>
Even without PDO in the way, the database won't return the structure without at least one row. You could do this and ignore the data row:
SELECT * FROM cf_pagetree_elements LIMIT 1;
Or you could simply
DESC cf_pagetree_elements;
and deal with one row per field.
WHERE 1=0 does not work for me. It always returns empty set.
The latest PDO for SQLSVR definitely works with get column meta.
Simply set up your statement and use this to get an array of useful information:
$stmt->execute();
$meta= array();
foreach(range(0, $stmt->columnCount() - 1) as $column_index)
{
array_push($meta,$stmt->getColumnMeta($column_index));
}
Complete solution for Oracle or MySQL
for any or some columns (my goal is to get arbitrary columns exactly as they are in DB regardless of case)
for any table (w or w/o rows)
$qr = <<<SQL
SELECT $cols
FROM (SELECT NULL FROM DUAL)
LEFT JOIN $able t ON 1 = 0
SQL;
$columns = array_keys($con->query($qr)->fetchAll(PDO::FETCH_ASSOC)[0]);
if($cols === "*") {
array_shift($columns);
}
YOu could use MetaData with;
$cols = mysql_query("SHOW COLUMNS FROM $tableName", $conn);

Categories