problem in fetching from complicated mysql table - php

I'm using an if clause to fetch the value of my mysql table data because my table schema is not normal.
now for getting these values, I wrote the below code:
$result = $db->sql_query("SELECT type, var, count from table_counter");
while ($row = $db->sql_fetchrow($result)) {
$type = $row['type'];
$var = $row['var'];
$count = intval($row['count']);
if(($type == "total") && ($var == "visits")) {
$totalVisits= $count;
}elseif(($type == "total") && ($var == "pageviews")) {
$totalPVisits= $count;
}
}
Is there any other way rather than using an if clause?!

SELECT `type`, `var`, SUM(`count`) AS `sum`
FROM table_counter
GROUP BY `type`,`var`;
There's no need for that intval() to convert the count field to integer. It's already defined as an integer in your MySQL table.

What you have here is some kind of EAV data structure and the if is a common way to fetch from it. There are other ways of pivoting them.

What are you aiming to do with the data? Just create the counts?
You could extract the data in more than one query.
Another option is to put the data into an array, then sort it using PHP array sort functions. It could then be split it into two separate arrays, if needed.

You will need to pivot the data. And that will require you to write some code to parse out what you need in php and mysql. This will can get heavy depending on how much data you want and how it's stored and how it needs to be retrieved. Based on your question text it looks you are storing very simple data, but for every type and set of data you are storing you will need to create logic for it.
Soooo, if you know exactly what the variables are going to be you could set up and array of the variable names you want set and loop through them.
$legal_values = array('visits', 'pageviews', etc...);
while ($row = $db->sql_fetchrow($result)) {
if (in_array($row['var'], $legal_values)) {
$$row['var'] = $intval($row['count'];
}
}
This is just a simple example and only works if all the types are count. Obviously if you want to filter it down you will need more logic. There isn't really a catch-all solution for this stuff, so it comes down to writing something that is simple so you understand it and you can easily extend it to handle more data that you might need later.

${$row['type'] . ucfirst($row['var'])} = $row['count'];
That reads total pageviews 107 to $totalPageviews = 107. Depending on where you want to use this, this may be a possibility.

Related

Sort an SQL query not a table

I have a database containing a large amount of information that a user can query using PHP to communicate with the MySQL database. I also want to limit their results to be at most 300 results, which I have successfully done. However, I also want to sort the results by dataset name. Is there a way to sort the end query, not the original table? From what I've read online, the ORDER BY statement in a query sorts the whole table and then does the query (or something similar) Sorting the query would be more efficient, as you would only be sorting say 15 records instead of 1500000. If it helps at all, I print the results to the page using the following syntax:
while ($row = mysql_fetch_array($result)) {
...
}
Thanks
If the result set is limited, save it into a php array then use the php sorting functions: http://php.net/manual/en/function.usort.php
$all = array();
while ($res = mysql_fetch_array($result)) {
$all[] = $res;
}
usort($all, function($a,$b) {
return $a['field'] < $b['field'];
});
Just make sure what you are sorting by has a decent index and the sort option should be very fast. The issue with sorting before/after a LIMIT is that if it were possible (which it is with a bit of GROUP BY logic), it would change the actual results you get as opposed to just the order they return in.
To create a sub table and only sort on that you could attempt something like:
Select * from ( QUERY limit 300) a order by COLUMN

php/mysql cascading filtering

I would like to create some chaining filters that a user can use to narrow down a list of data from the database.
For instance, I have 5 filters types:
by date
by location
by type
by topic
by keyword
The user is free to use all, some or none of these filters at once.
My first impression is that I would have to store a variable with all the "AND's" and "OR's" of my WHERE clause stacked one after the other but it seems tedious as I may have to programmatically add/delete some filter types later.
Is there a way not to use the whole mysql data that I filter once with one huge request but rather chain the targeted requests that I can add/withdraw if necessary?
I mean, can I filter one after the other the result of each previous filtered result?
For instance, instead of doing this:
SELECT * FROM mytable WHERE (A=3 AND B=4 AND ((C>date1) OR (D<date2)) AND D LIKE '%sample%' )
Is it possible to do something that would achieve this idea:
request 1 = SELECT * FROM mytable WHERE A=3
request 2 = SELECT * FROM "result of request 1" WHERE B=4
request 3 = SELECT * FROM "result of request 2" WHERE C>date1 OR D<date2
request 4 = SELECT * FROM "result of request 3" WHERE E LIKE '%sample%'
The first approach is very hard to manage if the filters are meant to change over time while the second approach is just a matter of adding/withdrawing the desired filter to the chain.
Not to mention that the more filters you have, the more the first approach becomes unreadable and unmanageable.
This could be obtained in pure php if I decide to filter the data after retrieving the whole mysql table but is seems counter productive and more verbose while Mysql has all I need to filter the data directly and it seems useless to get the whole data from Mysql when I only need part of it at the end.
Thank you for your help.
I like the first scenario better, I assume you're submitting a form to decide what to filter. The way I would go about making it scalable and easier to read, is just name the form fields the same as your DB fields. Then you can either keep an array containing the fields you want to use, or make a db call to check if a field is one you want to use in the filter. a simple example.
$filterFields = array('startDate'=>'>',
'endDate'=>'<',
'location'=>'=',
'keyword'=>'LIKE');
function buildQuery($filterFields, $mysqli)
{
$partCount = 0;
$query = "SELECT * FROM mytable WHERE ";
foreach($_POST as $key=>$value)
{
//is the field one we want to use? Does it contain a value?
if(in_array($key, array_keys($filterFields) && !empty($value))
{
if($partCount > 1)
$query .= ' AND ';
if($filterFields[$key] == 'LIKE')
$query .= " `".$key."` LIKE '%".mysqli->real_escape_string($value)."%' ";
else
$query .= " `".$key."` ".$filterFields[$key]." '".mysqli->real_escape_string($value)."' ";
++$partCount;
}
}
return $query;
}
Hopefully that makes sense. If that's not doing what you want or you need clarification, let me know. Also this is not tested, just wrote it here.

How to filter by multiple fields in MySQL/PHP

I'm writing a filter/sorting feature for an application right now that will have text fields above each column. As the user types in each field, requests will be sent to the back-end for sorting. Since there are going to be around 6 text fields, I was wondering if there's a better way to sort instead of using if statements to check for each variable, and writing specific queries if say all fields were entered, just one, or just two fields, etc.
Seems like there would be a lot of if statements. Is there a more intuitive way of accomplishing this?
Thanks!
Any initial data manipulation, such as sorting, is usually done by the database engine.
Put an ORDER BY clause in there, unless you have a specific reason the sorting needs done in the application itself.
Edit: You now say that you want to filter the data instead. I would still do this at the database level. There is no sense in sending a huge dataset to PHP, just for PHP to have to wade through it and filter out data there. In most cases, doing this within MySQL will be far more efficient than what you can build in PHP.
Since there are going to be around 6 text fields, I was wondering if there's a better way to sort instead of using if statements to check for each variable
Definitely NO.
First, nothing wrong in using several if's in order.
Trust me - I myself being a huge fan of reducing repetitions of code, but consider these manually written blocks being the best solution.
Next, although there can be a way to wrap these condition ns some loop, most of time different conditions require different treatment.
however, in your next statements you are wrong:
and writing specific queries
you need only one query
Seems like there would be a lot of if statements.
why? no more than number of fields you have.
here goes a complete example of custom search query building code:
$w = array();
$where = '';
if (!empty($_GET['rooms'])) $w[]="rooms='".mesc($_GET['rooms'])."'";
if (!empty($_GET['space'])) $w[]="space='".mesc($_GET['space'])."'";
if (!empty($_GET['max_price'])) $w[]="price < '".mesc($_GET['max_price'])."'";
if (count($w)) $where="WHERE ".implode(' AND ',$w);
$query="select * from table $where";
the only fields filled by the user going to the query.
the ordering is going to be pretty the same way.
mesc is an abbreviation for the mysql_real_escape_string or any other applicable database-specific string escaping function
select * from Users
order by Creadted desc, Name asc, LastName desc, Status asc
And your records will be sorted by order from query.
First by Created desc, then by Name asc and so on.
But from your question I can see that you are searching for filtering results.
So to filter by multiple fileds just append your where, or if you are using any ORM you can do it through object methods.
But if its simple you can do it this way
$query = "";
foreach($_POST['grid_fields'] as $key => $value)
{
if(strlen($query) > 0)
$query .= ' and '
$query .= sprintf(" %s LIKE '%s' ", mysql_real_escape_string($key), '%' .mysql_real_escape_string($value) .'%');
}
if(strlen($query) > 0)
$original_query .= ' where ' . $query;
this could help you to achieve your result.
No. You cannot avoid the testing operations when sorting the set, as you have to compare the elements in the set in same way. The vehicle for this is an if statement.
Could you take a look at this?
WHERE (ifnull(#filter1, 1) = 1 or columnFilter1 = #filter1)
and (ifnull(#filter2, 1) = 1 or columnFilter2 = #filter2)
and (ifnull(#filter3, 1) = 1 or columnFilter3 = #filter3)
and (ifnull(#filter4, 1) = 1 or columnFilter4 = #filter4)
and (ifnull(#filter5, 1) = 1 or columnFilter5 = #filter5)
and (ifnull(#filter6, 1) = 1 or columnFilter6 = #filter6)
Please let me know if I'm misunderstanding your question.. It's not like an IF statement batch, and is pretty lengthy, but what do you think?

php code, better way of grabbing sql data

I need to grab data from two tables, but I know theres a better, more tidier way to do this. Is it some kind of JOIN i need?
I'll show you my code and you'll see what I mean:
if ($rs[firearm] != "") {
$sql_result2 = mysql_query("SELECT * FROM db_firearms WHERE name='$rs[firearm]'", $db);
$rs2 = mysql_fetch_array($sql_result2);
$sql_result3 = mysql_query("SELECT * FROM items_firearms WHERE player='$id'", $db);
$rs3 = mysql_fetch_array($sql_result3);
if ($rs3[$rs2[shortname]] < 1) {
mysql_query("UPDATE mobsters SET firearm = '' WHERE id ='$id'");
}
}
This question is clear, but your code example has alot of formatting issues and I cannot give you direct answer, based on your example code.
The reason, why your example is unclear, is because.. with what are you going to join the tables? From one table you are selecting by name='$rs[firearm]' and from another by player='$id'. You have to provide the hidden data, like $rs and also $id.
You should definitely read these about mysql join and mysql left join. But I will try to give you an example based on your code, with fixed syntax. (Keep in mind, that I'm no mysql join expert, I did not test this code and also I do not know the joining conditions.) And also, the system structure is unclear.
As I understood, this what your tables do, correct?
mobsters - Users table
items_firearms - Links from users table to items table
db_firearms - Items table
So basically, my example does this: It will have preloaded $rs value, from the users table. It will check, if there is a entry inside the links table and hook the result with them items table. However, if the links table or even the items table can return multiple entries, then this doesn't work and you need to loop your results in much more smarter way.
// I can only assume, that $id is the ID of the player
$id = 2;
// Since I dont know the $rs value, then Im going to make some up
$rs = array(
'id' => 33,
'firearm' => 'famas'
);
if ($rs['firearm']) {
$result = mysql_fetch_array(mysql_query("SELECT ifa.*, dbfa.* FROM `items_firearms` AS `ifa` LEFT JOIN `db_firearms` AS `dbfa` ON `ifa.shortname` = `dbfa.shortname` WHERE `ifa.player` = '$id'"));
if ($result['id']) {
mysql_query("UPDATE `mobsters` SET `firearm` = '' WHERE `id` = '$id'", $db);
}
}
It is pretty clear, that you are new to PHP and mysql.. So I think you should probably edit your question and talk about your higher goal. Briefly mention, what your application are you building..? What are you trying to do with the mysql queries..? Maybe provide the table structure of your mysql tables..? I'm sure, that you will get your questions votes back to normal and also we can help you much better.
NOTES
You have to quote these types of variables: $rs[firearm] -> $rs['firearm']
If you want to check if your $rs['firearm'] equals something, then there is a better way then $rs[firearm] != "". The most simple is if ($rs['firearm']) {echo 'foo';}, but will produce a notice message, when all errors reporting mode. You can use isset() and empty(), but keep in mind, that isset() checks whether the variable has been set.. Meaning, even if its false, then it has been set. empty() reacts to undefined and empty variable the same, without any messages.
Also, "" means NULL, so if you even need to use "", then use NULL instead...much neater way..
I strongly recommend to use mysql class. You can understand the basics behind that idea from this answer. This is gonna make things much more easier for you. Also, mysql class is a must-have when dealing with dynamic applications.
if ($rs3[$rs2[shortname]] < 1) { .. makes no sense.. Do you want to check if the value is empty? Then (simple): if (!$rs3[$rs2[shortname]]) { .. and a very strict standard: if (empty($rs3[$rs2[shortname]])) { ..
Also you have to quote your sql queries, see my examples above.
Is the last mysql query missing $db?

How do I organize an array that is an html line containing variables pulled from mysql table?

I am attempting to alphabetically organize an options list populated from an array; the problem is that the array array contains html tags at the front so sorting it seems imposable. I have tried 'ORDER BY' in the mysql query from which the array variables are pulled, but the command gets lost.
The whole system seems hardwired to sort the list by the key column in the mysql table, which is simply not acceptable. Is there any way around this issue? Any help would be VERY appreciated!
Here is an example of what I'm trying to do:
$options = array();
$query1=mysql_query("Select * From table1 Where name='blah'");
while($queryvalue1=mysql_fetch_array($query1)) {
$array1 = $queryvalue1['Column1'];
$query2=mysql_query("Select * From table2 Where id In ($array1) Order by value DESC");
while($queryvalue2=mysql_fetch_array($query2)) {
$var1 = $queryvalue2['Column2'];
$var2 = $queryvalue2['Column3'];
$options[] = "<option value='$var'>$var2</option>"
}
}
$options = implode(PHP_EOL, $options);
There's certainly ways to do it, but they are all much slower than letting the database sort for you.
It might not be the simplest solution, but I'd suggest getting rid of the HTML tags and repopulating the database, even if you have to use a temporary table while you fix the rest of your code. Do it right so you don't have to continually work around a serious problem for the rest of the application lifecycle.

Categories