if i have a query like :
SELECT * FROM table WHERE id IN (3,6,1,8,9);
this array of the ids is build in php dynamically ,
and the order is important to me.
$my_array = array (3,6,1,8,9) ;
how can i sort the results by the order by which the elements appear in my array ?
its possible to do it in MYSQL query,
or i must to order it after via php ?
You can order by a value derived from a column. You can use a CASE operator to specify the order:
SELECT * FROM table
WHERE id IN (3,6,1,8,9)
ORDER BY CASE id WHEN 3 THEN 1
WHEN 6 THEN 2
WHEN 1 THEN 3
WHEN 8 THEN 4
WHEN 9 THEN 5
END
I haven't tested but this PHP solution should work:
<?php
$my_array = array (3,6,1,8,9) ;
$sql = 'SELECT * FROM table WHERE id IN (3,6,1,8,9)';
$sql .= "\nORDER BY CASE id\n";
foreach($my_array as $k => $v){
$sql .= 'WHEN ' . $v . ' THEN ' . $k . "\n";
}
$sql .= 'END ';
echo $sql;
?>
This generates the following SQL code:
SELECT * FROM table WHERE id IN (3,6,1,8,9)
ORDER BY CASE id
WHEN 3 THEN 0
WHEN 6 THEN 1
WHEN 1 THEN 2
WHEN 8 THEN 3
WHEN 9 THEN 4
END
If you must do it this way you'll have to manipulate the data in PHP. MySQL can only order by natural orderings ascending or descending.
Got to question though - why do you need the data returned in this very specific order? There may be an easier solution to your problem by re-jigging something further up in the code.
SELECT * FROM table WHERE id IN (3,6,1,8,9) ORDER BY FIELD(id,3,6,1,8,9);
You can load the results into an array with IDs as indexes:
while ($row = mysql_fetch_array($l)) $items[$row['id']] = $row;
and then simply iterate it in your order
foreach ($my_array as $id) { $current_row = $items[$id]; ... }
Related
I have a strange issue happening. I've got a table where I want to order the number of times a product was sold. I'll post the query, but the issue is inside the while loop.
Query:
$cat = $db->query("SELECT *, COUNT(id_produto) as quantos FROM produtos p JOIN pedidos m ON p.id_prod = m.id_produto GROUP BY id_produto ORDER BY quantos +0 DESC");
$cat->execute();
Now the loop:
while($res_cat = $cat->fetch(PDO::FETCH_ASSOC)){
$quantidade_ok = $res_cat['quantos'] * $res_cat['qtde'];
$quanti = array($quantidade_ok);
rsort($quanti);
foreach($quanti as $ord){
echo $ord."<br>";
}
The output is:
40
50
4
1
3
2
10
But I want it to be:
50
40
10
4
3
2
1
I'll be happy for any help.
You're sorting within a loop (so your sorting already happened), and you're sorting an array with just 1 value $quanti, so your sort does nothing.
You have 2 ways to approach this properly: edit your query to actually sort how you wish, or sort the PHP array before looping it.
Option 1: Edit your query
Based on your code it seems clear that you wish to sort by the product of quantos times qtde. So you can simply edit your query as follows:
SELECT *, COUNT(id_produto) as quantos
FROM produtos p JOIN pedidos m ON p.id_prod = m.id_produto
GROUP BY id_produto
ORDER BY (quantos*qtde) DESC
Option 2: Sort via PHP
If you prefer to sort via PHP as you don't want to change your query, you can simply populate a temporary array, the product of quantos times qtde as key and then use krsort to sort the array.
In code:
$array = [];
while ($res_cat = $cat->fetch(PDO::FETCH_ASSOC)) {
$key = $res_cat['quantos'] * $res_cat['qtde'];
$array[$key] = $res_cat;
}
krsort($array);
foreach ($array as $ord => $res_cat) {
echo $ord."<br>";
}
You overwrite $quanti each time so it always has a single value.
Try this:
$quanti = [];
while($res_cat = $cat->fetch(PDO::FETCH_ASSOC)) {
$quantidade_ok = $res_cat['quantos'] * $res_cat['qtde'];
$quanti[] = $quantidade_ok;
}
rsort($quanti);
foreach($quanti as $ord){
echo $ord."<br>";
}
This question already has answers here:
MySQL sort after argument in IN()
(4 answers)
Closed 8 years ago.
I have a table like below, id being the primary key
ID Name
1 a
2 b
3 c
4 d
5 e
and have a query like below. This query is created in a php file from user input choices.
select name from table where id in (1,5,3)
I get the result ("a", "c", "e") which I guess is normal because of the default primary key sort order. However I want result to be ordered in the same sequence as the "in" clause. So I want returned value to be ("a", "e", "c"). Is there any way to get it in mysql.
You can simply use FIELD():
select name from TableName where id in (1,5,3)
ORDER BY field(id,1,5,3)
Result:
NAME
a
e
c
See result in SQL Fiddle.
You can use a CASE operator to specify the order:
SELECT * FROM table
WHERE id IN (3,6,1,8,9)
ORDER BY CASE id WHEN 3 THEN 1
WHEN 6 THEN 2
WHEN 1 THEN 3
WHEN 8 THEN 4
WHEN 9 THEN 5
END
in php u can do it like :
<?php
$my_array = array (3,6,1,8,9) ;
$sql = 'SELECT * FROM table WHERE id IN (3,6,1,8,9)';
$sql .= "\nORDER BY CASE id\n";
foreach($my_array as $k => $v){
$sql .= 'WHEN ' . $v . ' THEN ' . $k . "\n";
}
$sql .= 'END ';
echo $sql;
?>
I have mysql table that looks like this:
id place interest
1 place1 a,b,c
2 place2 c,d,e
3 place1 a,e
4 place2 f
5 place2 f
6 place3 g,h
I need to get unique "place" and "interest" values sorted as per the count.
So, the output for "place" would be
place2(3)
place1(2)
place3(1)
So, the output for "interest" would be
a(2)
c(2)
e(2)
f(2)
b(1)
d(1)
g(1)
h(1)
is there a way to do this in PHP-Mysql?
So, far I have been able to get simple column data
SELECT place,
COUNT( * ) AS num
FROM testtab
GROUP BY place
ORDER BY COUNT( * ) DESC
As mysql is not able to hold arrays, its better to build a new table like this:
interest_id interest_name
1 a
2 b
and another one to keep the relations:
pk id interest_id
1 1 1
2 1 2
which this id is the id of the records in your main table.
With having this, you can easily use:
select count(*) from THIRD_TABLE where id = YOUR_ID
You can do this.
$place = array();
$interests = array();
foreach($rows as $row){
if (!isset($place[$row["place"]])){
$place[$row["place"]] = 0;
}
$place[$row["place"]]++;
$ints = explode(",", $row["interests"]);
foreach($ints as $int){
if (!isset($interests[$int])){
$interests[$int] = 0;
}
$interests[$int]++;
}
}
This will give you the two arrays keyed off of the relevant field with the value being the count. If this is going to be a common action in your application it would make more sense to normalize your data as suggested by AliBZ.
This is for the first result you need
SELECT place,COUNT(interest)
FROM `testtab`
GROUP by place
ORDER BY COUNT(interest) desc
can do this :
$inst_row = '';
foreach($rows as $row){
$inst_row .= $row['interests'];
}
$inst_values = explode(',', $inst_row);
$inst_count = array_count_values($inst_values);
// $inst_count will return you count as you want ,print_r it and format it accordingly
MySQL table: name, salary, childrens, brothers, age
I'm trying to retrieve the name of the person who has the max value in salary, childrens and brothers, with age>30. Note: every name is unique.
To do achieve this I loop through all columns whit this array:
$columns = array('salary','childrens','brothers')
foreach($columns as $value){
$result=mysql_query("SELECT `name`, `$value` FROM table_name WHERE `age`>30 ORDER BY `$value` ASC LIMIT 1");
while($rows=mysql_fetch_array($result,MYSQL_ASSOC)){
echo $rows[name];
};
};
Everything works fine, but I would also like to count the amount of times each name is retrived (echoed).
i.e.: Max has the highest salary and the highest amount of brothers, so his name has been retrivied 2 times. Loren only has the highest amount of childrens, so his name has been retrivied 1 time. Jason has never been retrivied, so it's 0 for him.
I tried this:
$i=0;
$columns = array('salary','childrens','brothers')
foreach($columns as $value){
$result=mysql_query("SELECT `name`, `$value` FROM table_name WHERE `age`>30 ORDER BY `$value` ASC LIMIT 1");
while($rows=mysql_fetch_array($result,MYSQL_ASSOC)){
echo "The person who has the max amount of $value is $rows[name]";
$count[$rows[name]] = $i++;
};
};
But it doesn't work as intended, it counting the number of times eache name appears in every columns without taking into account if it has the max value.
Any help would be appriciated.
ps: if you also can improve the code the retrivie the max value I would be grateful.
UPDATE:
The query for each table should output this:
Name salary
Max 2000
--
Name childrens
Loren 4
--
Name brothers
Max 3
The $count array should be:
$count = array('Max'=>2,'Loren'=>1,'Jason'=>0,'etc'=>0);
You used the same counter for all names. Try to split them. Something like that:
$count=array();
$columns = array('salary','childrens','brothers')
foreach($columns as $value) {
$result=mysql_query(
"SELECT `name`, `$value`
FROM table_name
WHERE `age`>30
ORDER BY `$value` ASC
LIMIT 1"
);
while($rows=mysql_fetch_array($result,MYSQL_ASSOC)) {
echo "The person who has the max amount of $value is $rows[name]";
if(!isset($count[$rows[name]]))
$count[$rows[name]] = 0;
++$count[$rows[name]];
};
};
print_r($count);
UPD: And also if you need a row with MAX value, you must use DESC instead of ASC
UPD2: To retrieve all the users, you need also execute SELECT DISTINCT name FROM table_name before previous code and fetch it into array $count[$r['name']] = 0
I'm not sure what you up to , but in programing i will use comparing method to get highest value , but there is another MAX() function in server side language to get greatest value of all record http://www.w3schools.com/sql/sql_func_max.asp
$columns = array('salary','childrens','brothers');
$highest = array(array('salary'=>0,'childrens'=>0,'brothers'=>0));
foreach($columns as $value){
$result=mysql_query("SELECT `name`, `$value` FROM table_name WHERE `age`>30 ORDER BY `$value` ASC LIMIT 1");
while($rows=mysql_fetch_array($result,MYSQL_ASSOC)){
//compare the value of each record if greater then replace
if($highest[$value]<$rows[$value]){
//replace with current highest value and set name into array
$highest[$value]=$rows[$value];
$highest[$value]=$rows[name];
}
};
};
print_r($highest);
So there is this database table:
and this array with selected options:
$options[1] = 1;
$options[2] = 5;
$options[3] = 3;
$options[4] = 2;
$options[5] = 1;
...
$options[x] = y;
Now, the aim is to fetch all item_ids, where if there is an option_id in its row from one of the options array's keys, the value must be the same as the value in the options array.
For example:
option 1 has selected value 1
option 2 has selected value 5
option 3 has selected value 4
option 4 has selected value 2
so we should select item_id 1 and other item_ids, where if option 1 -> option 1 = 1 AND if option 2 -> option 2 = 5 AND if option 3 -> option 3 = 4 AND ...
The item_ids will be used in IN() to select the items data from the items table.
The main point is that the user selects some options on a page, then the options are put into array, then I must find all items that comply with the selected options. In the table above we have the relation between the items and the options, and the option values per item which are predefined.
$where = array();
foreach($options as $key => $value) $where[] = 'option_id = ' . $key . ' AND option_value = ' . $value;
$sql = 'SELECT DISTINCT item_id
FROM table
WHERE (' . explode(') OR (', $where) . ')';
I might have completely misunderstood your question however.
I think this might do it for you. Haven't tested it at all and it'll probably blow up, but...
SELECT *
FROM items
WHERE (item_id in (
SELECT item_id
FROM optiontable
WHERE ((option_id = 1) and (option_value = 1)) or
((option_id = 2) and (option_value=5)) or
((option_id = 3) and (option_value=3)) or
((option_id = 4) and (option_value=2)) or
((option_id = 5) and (option_value=1))
GROUP BY CONCAT(option_id, ',', option_value)
HAVING COUNT(CONCAT(option_id, ',', option_value)) = 5
));
Basically, the inner query pulls out all the rows that match one of the member rows in your required options row. It does an artificial grouping/count on the paired option_id/option_value pairs and returns the item_ids of the rows where the number of opt_id/opt_val pairs add up to 5 rows.
You'd have to build such a query dynamically in the client, so that the number of 'where' clause entries matches the number in the having clause.
<?php
$options = array(
1 => 1,
2 => 5,
3 => 3,
4 => 2,
5 => 1
);
$cases = array();
foreach($options as $id => $value){
$cases[] = "WHEN $id THEN $value";
}
$query =
'SELECT item_id '.
'FROM your_table '.
'WHERE option_value = CASE option_id '.implode(' ', $cases).' '.
'GROUP BY item_id';
echo $query;
?>
Output (formatted by me):
SELECT item_id
FROM your_table
WHERE option_value = CASE option_id
WHEN 1 THEN 1
WHEN 2 THEN 5
WHEN 3 THEN 3
WHEN 4 THEN 2
WHEN 5 THEN 1
GROUP BY item_id
Test this query and let me know if it works the way you expect it to. :)
Update: Suggestion for your final query
$query =
'SELECT * FROM items '.
'WHERE id IN('.
'SELECT item_id '.
'FROM your_table '.
'WHERE option_value = CASE option_id '.implode(' ', $cases).' '.
'GROUP BY item_id)';