Sorting mysql query in php - php

I get from db rows in order 10, 12, 13, 21, 06, 02, 08
I need that this will be sorted like this: 02, 06, 08, 10, 12, 13, 21
Order by field ASC doesnt work i need. I tried remove zeros and then sort array, but no results. Any thoughts?
Omeri
sort(ARRAY) did the trick
$sql = "SELECT DISTINCT l, item, l, s FROM tr WHERE s = '".$_POST['size']."' AND type = '".$type."' ORDER BY l ASC";
$res = mysql_query($sql,$this->conn);
$type = '<option selected="selected" disabled="disabled"></option>';
while($row = mysql_fetch_array($res)){
$caption[] = $row;
}
sort($caption);
foreach($caption as $row) {
$length = substr($row['item'], strrpos($row['item'], '-') + 1);
$type .= '<option value="'.$length.'">'.$length.'</option>';
}

change the column type of those numbers to INT then u get them ordered.
i think you have your colum now as CHAR or VARCHAR

#Eric Petroelje I would use:
SELECT * FROM table ORDER BY CAST(col AS SIGNED) ASC
Or add zeros in front of all your numbers. For example, 1 becomes 0001 and 2 becomes 0002 that way you will have your zeros and they will also sort. Oh, I see that you have commented below that your are also using 02 and 2. So you can disregard this.
Or add an extra INT column with the correct order.

The sorting should be done via the MySQL server. If you aren't getting the proper order, then your query might be wrong. Another problem could be that you are storing your numbers as text or another data type?
However, to remove 0's in the beginning, you can cast the variable explicitly to a integer:
$numstring = (int)$realint;

Sounds like the data is stored in MySQL as a CHAR or VARCHAR, so when the column is ordered, it's ordering it like it's a string rather than a number.
Other than changing the type of the column to an INT, you could force MySQL to treat it as an integer for ordering (assuming all values in the column are numbers) like so:
SELECT fields
FROM mytable
ORDER BY CAST(col AS SIGNED)

Related

Identifying the number of rows within a specific value range using PHP

I am trying to figure out how to determine the total number of rows within a specific number range using PHP.
I have a simple MySQL table with a single column. The column contains thousands of rows, each row containing a number between 0 and 100.
I figured out how to find the number of rows for a specific number, using array_count_values, but I can't figure out how to find the number of rows for a range.
For example, how many numbers are there between 60 and 80?
Here is the code that I put together to find a single value. What code should I add to find range values?
$query = "SELECT numbers FROM table";
$result = mysqli_query($conn, $query) or die("Error in $query");
$types = array();
while(($row = mysqli_fetch_assoc($result))) {
$types[] = $row['numbers'];
}
$counts = array_count_values($types);
echo $counts['12'];
If you need to count within multiple ranges you can use UNION so you don't have to send 5 queries.
$query = "SELECT COUNT(numbers) FROM `table` WHERE numbers between 00 and 20
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 20 and 40
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 40 and 60
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 60 and 80
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 80 and 100";
You can do this several ways.
Simple way (one full table scan)
SELECT SUM(IF(x BETWEEN 20 AND 30, 1, 0)) AS b_20_30,
SUM(...) AS b_31_40,
...
FROM tableName...
will return only one row with all your results in the time of a table scan.
Fancy way (not really recommended)
If you can come up with a rule to map your intervals to a single number, for example:
0...9 => interval i = 0
10...19 => interval i = 1 => the rule is "i = FLOOR(X/10)"
20...29 => interval i = 2
...and you don't need to scan too many rows, you might do something not very maintainable like this:
SELECT SUM(FLOOR(POW(100, FLOOR(x / 10)))) AS result FROM tableName;
Here, a value of 25 (between 20 and 29) will become 2, and the total sum will be increased by 1002. So long as you never have more than 100 rows in each group, the final result will be a univocal sum of powers and, if you have - say - 17 rows between 0 and 9, 31 rows between 10 and 19, and 74 between 20 and 29, you'll get a "magical parlor trick" answer of
743117
from whence you can recover the number of rows as 74,31,17 in that order.
Using 1000 instead of 100 would yield 74031017 (and the possibility of coping with up to 999 numbers in each group).
Note that the use of functions inside the SELECT pretty much guarantees you'll need a full, slow table scan.
Using indexes for speed
But we can get rid of the table scan, and simplify generation, by judiciously using indexed WHEREs - this is identical, performance-wise, to a UNION, but the result is simpler since it is only one row:
SELECT (SELECT COUNT(*) FROM tableName WHERE x BETWEEN ...) AS b_20_30,
(...)
; -- no table name on the outer query
This will need several subqueries (one per interval), but those subqueries will all use an index on x where available, which can make the overall query very fast. You just need
CREATE INDEX x_ndx ON tableName(x);
The same index will greatly improve the performance of the "simple" query above, which will no longer need a table scan but only a much faster index scan.
Build the query using PHP
Supposing we have the intervals specified as convenient arrays, we can use PHP to generate the query in the first place. No need of manually entering all those SELECTs.
$intervals = [ [ 20, 30 ], [ 17, 25 ], ... ];
function queryFromIntervals(array $intervals) {
$index = 0;
return 'SELECT ' .
implode(',', array_map(
function($interval) use ($tableName, &$index) {
return "(SELECT COUNT(1) FROM {$tableName} WHERE x BETWEEN {$interval[0]} AND {$interval[1]}) AS b_" . ($index++);
},
$intervals
))
// . ", (SELECT COUNT(*) FROM {$tableName}) AS total"
. ';';
}
This will again yield a single row, with fields named b_0, b_1, and so on. They will contain the number of rows where the value of x is between the bounds of the corresponding interval in $intervals (the intervals may overlap).
So by executing the query and retrieving a tuple called $result, you might get
[ 'b_0' => 133, 'b_1' => 29 ]
meaning that there are 133 rows with x between 20 and 30, and 29 with x between 17 and 25. You can add to the query a last total field (commented in the code above):
, ... ( SELECT COUNT(*) FROM tableName ) AS total;
to also get the total number of rows.
The same function, changing the inner return value, can be adapted to generate the "simple" query which uses IFs instead of SELECTs.
Why not let the database do the heavy lifting for you?
$query = "SELECT COUNT(*) FROM table WHERE numbers BETWEEN 60 AND 80";
$result = mysqli_query($conn, $query) or die("Error in $query");
$row = mysqli_fetch_array($result, MYSQLI_NUM);
echo $row[0];
If I understood well, you try to put a condition in your request sql.
Look that https://www.w3schools.com/sql/sql_where.asp
$query = "SELECT numbers FROM table WHERE numbers >= 60 AND numbers <= 80";

Using age and gender to search for ID numbers in a table

In an interface where user records in a table can be searched.
The operator must be able to search by the age and/or the gender of the user(the record). However this must be done by using the ID number of the user captured.
This is possible, as the ID number can be broken down into usable data.
An ID number has 13 DIGITS:
eg. 6911205062080
Which can be broken down as follows:
YYMMDDSSSSCAZ
Where (YYMMDD) refers to date. 20 November 1969 is shown as 691120
(SSSS) refers to gender. Females are assigned numbers in the range 0000-4999 and males from 5000-9999
CAZ also carries meaning however they are not relevant to the context of the question. `
The user can choose to search All ages, or select from three age brackets:
A:18-38, B:39-59, C:60 upwards.
-They can select one option[ A or B or C]
-Or They can select two options[A and B,A and C or B and C],
-Or They can select all 3 options[A and B and C], meaning all of them)
This means that if they op not to search all of the age groups, an array containing their selection gets posted.
When selecting gender:
-They can search all genders[Male & Female]
-Or Choose one option [Either Male or Female]
The data gets sent to me and now I have to manipulate the data to return the correct records.
Now I know I have to use substrings. The ID field is stored as character varying however to establish the age I would have to substring the (YYMMDD) part and cast it to a date in order to correctly compare it, and the (SSSS) would have to be cast to an integer to establish if it is smaller than 5000
This is my code so far:
if($_POST['gender'] == 'all'){
$gender="";
}elseif($_POST['gender'] == 'male'){
$gender = " and userIDNumber = "."ESTABLISH ALL ID's THAT ARE MALE";
}elseif($_POST['gender'] == 'female'){
$gender = " and userIDNumber = "."ESTABLISH ALL ID's THAT ARE FEMALE";
}
$age = "";
if($_POST['radioAge'] == 'select'){
$branches = " and userIDNumber in (SELECT A WAY TO FIND OUT HOW TO ESTABLISH THE AGES THAT FALL IN THE GROUPS SPECIFIED BY THIS ARRAY in(". implode(",", $_POST['age_group']).")) ";
}
$query = "SELECT * FROM user_table WHERE status='Active'".$gender.$age;
Using PHP and SQL, how would I go about using the posted gender selections and age selections to find the correct ID numbers and as a result, the correct records?
for the gender try something like this:
if($_POST['gender'] == 'all'){
$gender="";
}elseif($_POST['gender'] == 'male'){
$gender = "and CONVERT(SUBSTR(userIDNumber, 6, 4), INTEGER) < 5000";
}elseif($_POST['gender'] == 'female'){
$gender = "and CONVERT(SUBSTR(userIDNumber, 6, 4), INTEGER) >= 5000";
}
First you need to extract the information from the ID-s for the year part:
You need to use substring and string contatenation for this.
After that you need convert it to date and use the now() function to get the date difference. SELECT DATEDIFF(year, '2011-10-02', '2012-01-01');
Finaly you need to create between branches like this:
... where DATEDIFF(year, '2011-10-02', now()) between 18 and 38 ...
Gender:
Same way, extract the information from id with substring, cast it to numeric.
... where CAST(substring(ID) as numeric) <5000 --female
You also need to create the AND , OR operators.

MYSQL select mulitiple fields / columns from the table's row that are not empty

I have 12 columns on the below code and I want the best, correct and short way to select only fields for a user order(a row) where the field is not empty/0 in the table.(all fields are INT and numbers are less than 500)
$conn = mysqli_connect("localhost", "root", "","table_name") or die("error");
$sql = "SELECT dqnt_91,deal_91,dqnt_92,deal_92,dqnt_93,deal_93,dqnt_94,deal_94,dqnt_95,deal_95,dqnt_96,deal_96 FROM table_name WHERE fid='$userid' AND COLUMNS ARE NOT EMPTY ";
$result = mysqli_query($conn, $sql);
while( $row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
$d_91 = $row['deal_91']; $d_92 = $row['deal_92']; $d_93 = $row['deal_93']; $d_94 = $row['deal_94']; $d_95 = $row['deal_95']; $d_96 = $row['deal_96'];
$qnt_91 = $row['dqnt_91']; $qnt_91 = $row['dqnt_92']; $qnt_91 = $row['dqnt_93']; $qnt_91 = $row['dqnt_94']; $qnt_91 = $row['dqnt_95']; $qnt_91 = $row['dqnt_96']; }
echo 'You have selected:'.$d_91.'for'.$deal_91.'<br>';
echo 'You have selected:'.$d_92.'for'.$deal_92.'<br>';
echo 'You have selected:'.$d_96.'for'.$deal_96.'<br>';
Again, I want echo out only those fields that are not zero(0) or empty and if they are zero value then don't show or echo them!
The code below can work but because I have 12 columns and can add more to them then the below code is not handy.
SELECT [ all 12 x columns_name] FROM table_name WHERE table_name.column_name1!='' AND table_name.column_mame2!='' AND x another 10 times the last code ;
Thanks,
Short of modifying the data structure, you won't do much better in SQL than listing the 12 columns each with its own condition; and anything shorter will come at a cost of clarity, so personally I'd advise against it. But if brevity is more important than clarity for your application:
If you can add a view, it could provide a simple flag for you to test against.
create view my_view as (select -- each column
, case when -- all values are present
then 1 else 0 end nonempty_flg
from -- ...)
Then at least the complexity is hidden away from the calling app. If that's not an option:
You state the columns are small integer values. If you can further assume they're non-negative, then you can sum them up and compare against 0. If the might be negative, you could sum their absolute values.
In your examples the columns are treated as strings. If they are in fact CHAR or VARCHAR, you could concat them all and check the result against empty. You might have to coalesce null values to '' as you go.
But it sounds like what you really want is something that works without the query knowing in advance the set of columns; that's not doable in SQL. I suppose you could write a function/method/procedure in your calling program to generate the query based on examining the table columns in the catalog.

SUM SQL value to increment values per session

This is very awkward, this is a very simple fetch value, equal to otherwise sum one and then save... but is not working...
I have a predefined value as 1010, so, I select the last entry in the SQL, if the last entry is grater than 1010 then get the value and add 1, then save it which now the last value would be 1011 correct? but is not....
$values_b = 1010;
$getval = 'SELECT number FROM table ORDER BY number DESC LIMIT 1';
$final = $con->query($getval);
$vals = $final ->fetch_array();
$numbers = $vals['number'];
if ($numbers > 1010){
$new_n = $numbers + 1;
$new_numbers = 'INSERT INTO table (number) VALUES ('$new_n')';
$con->query($new_numbers);
} else {
$new_numbers = 'INSERT INTO table (number) VALUES ('$values_b')';
$con->query($new_numbers);
}
Very simple, but the result some how is awkward, it doesn't save 1010 or 1011 or any of the sort... instead is saving 2325 and why is that???? I don't use this values anywhere else, those are unique variables but I really don't understand, this is the first time this is happening, my table is utf-8-general-ci and the column is INT(20) I have try VARCHART(100) but the result is almost the same...
What I'm trying to achieve is "simple", I have a per-defined number 1010, so, if this is the first record save that number 1010, if not, then get the last record say 1020 which mean that there are 10 records, just sum 1 to the last record 1020 + 1 = 1021 and save it... see, very simple, but for some reason is not doing it... so I was wondering if someone can help me solve this...
Thank you for taking the time
SOLVED
The problem here was the query, I was calling to a column with the incorrect name
this table has about 19 columns, the first 5 are
ID | Name | email | numbers ..... the column 16 is | number |
I was calling number when in reality I should be calling for NUMBERS the result that I was getting was from another file, so, in other words, I was getting the result from B and adding 1 to B when I should be using A...
this is entirely my fault, I should paid more attention... sorry guys...
Try this:
$values_b = 1010;
$getval = 'SELECT max(number) as bignumber FROM table';
$final = $con->query($getval);
$vals = $final ->fetch_array();
$numbers = $vals['bignumber'];
if ($numbers > 1010){
$new_n = $numbers + 1;
$new_numbers = 'INSERT INTO table (number) VALUES ('$new_n')';
} else {
$new_numbers = 'INSERT INTO table (number) VALUES ('$values_b')';
}
$con->query($new_numbers);

PHP function - custom string length function

In php what is a function to only display strings that have a length greater than 50 characters, truncate it to not display more than 130 characters and limit it to one result?
so for example say i have 30 rows in a result set but I only want to show the newest row that have these parameters. If the newest row has 25 characters it should not display. It should only display the newest one that has a string length of 50 or more characters.
Use an SQL query. For finding the newest you want max on either an auto_increment primary key (ill call it id) or a date/time when the row was created (say, time time_created).
So I am assuming table with: id (int), stringVal (string, char(), varchar(), whatever)
SELECT MAX(id), SUBSTRING(stringVal, 1, 130)
FROM yourTable
WHERE LENGTH(stringVal) > 30
Replace id with a time field if you have to. You're going to have a hard time finding the newest without one of them, but you can always arbitrarily pick one row.
--Edit-- a sample of using mysql functions in PHP to run above query and fetch desired output
$sql = "SELECT MAX(id), SUBSTRING(stringVal, 1, 130) FROM yourTable WHERE LENGTH(stringVal) > 30";
$r = mysql_query($sql, $conn); //im hoping $conn or something like it is already set up
$row = mysql_fetch_assoc($r);
$desiredString = $row['stringVal'];
Something like this should do just make sure that you grab your data sorting by the newest items first. The break statement will ensure that the loop is terminated after the first result matching your criteria is found...
foreach($array_returned_from_query as $row)
{
if(strlen($row) > 50)
{
echo substr($row, 0, 130);
break;
}
}

Categories