I want to eliminate all the duplicates in a select dropdown list created with PHP.
My PHP code that creates the dropdown list is the following:
public static function getDropdownlist($conn)
{
//Initialize dropdown list
//--------------------------------------------------
$ddl_query = "select * from MIS_EMPLOYEES";
$stmt_ddl = oci_parse($conn, $ddl_query);
oci_execute($stmt_ddl);
//A default value -- this will be the selected item in the dropdown ##
$prosopiko = JRequest::getVar('bodies', 0);
if ($prosopiko == 0)
$default = 0;
else
$default = $prosopiko;
//Initialize array to store dropdown options ##
$options = array();
// $options = array_unique();
$options[] = JHTML::_('select.option', '0', 'Επιλέξτε');
while (($row = oci_fetch_array($stmt_ddl, OCI_ASSOC+OCI_RETURN_NULLS)) != false) {
$options[] = JHTML::_('select.option', $row['ID'], $row['POSITION']);
}
//Create <select name="month" class="inputbox"></select> ##
$dropdown = JHTML::_('select.genericlist', $options, 'bodies', 'class="inputbox"', 'value', 'text', $default);
return $dropdown;
}
}
But it brings all the duplicates written from an Oracle table.
How can I eliminate the duplicates? I tried array_unique but I failed.
In your SQL statement, simply change it to gather distinct elements you are interested in.
Since you are only using two values in the above code for the value and text, something like this should work:
SELECT ID, POSITION
FROM MIS_EMPLOYEES
GROUP BY ID, POSITION
Easiest option is to modify your query to SELECT DISTINCT ID, POSITION or GROUP BY ID, POSITION. Other than that you'll need to build up an array and use array_unique on that.
Related
We have a PHP script that loops through many XML / CSV files from different websites. Right now we manage to build a good XML / CSV parser script.
The PHP script we wrote is looping though some BIG XML or CSV files. In these XML or CVS files contains Barcodes from different products.
Right now before the script starts I fill an array with the Product ID + Barcode from the MySQL like this:
function Barcodes_Array() {
$sql = "SELECT ProductId, Barcode FROM Products WHERE (Barcode <> '') ";
$res = mysql_query($sql);
while ($rijen = mysql_fetch_assoc($res)) {
$GLOBALS['arrBarcodes'][] = $rijen;
}
}
Each time we loop through the XML (or CSV) files we have to check if the Barcode exists in the array and return the Product ID.
For searching in the function:
$ProductId = SearchBarcodeProduct($EanNr, 'Barcode');
And yet the function:
function SearchBarcodeProduct($elem, $field)
{
$top = sizeof($GLOBALS['arrBarcodes']) - 1;
$bottom = 0;
$ProductId = 0;
while($bottom <= $top)
{
if($GLOBALS['arrBarcodes'][$bottom][$field] == $elem) {
return $GLOBALS['arrBarcodes'][$bottom]['ProductId'];
}
else {
if (is_array($GLOBALS['arrBarcodes'][$bottom][$field])) {
if (in_multiarray($elem, ($GLOBALS['arrBarcodes'][$bottom][$field]))) {
return $GLOBALS['arrBarcodes'][$bottom]['ProductId'];
}
}
}
$bottom++;
}
return $ProductId;
}
We fill in the array because it took forever each time we ask the MySQL Products Table.
My Question is now:
It still takes a VERY long time each time looping through the array of the barcodes. Is there a faster way for any other solutions maybe a different way then a array?
Can someone help please i am working like weeks on this stupid :) thing!
Why do you need 2 functions?
Try just one
function itemBarcode($id) {
$id = intval($id);
$sql = "SELECT ProductId, Barcode FROM Products WHERE ProductId = $id Barcode <> '') ";
$res = mysql_query($sql);
if ($row = mysql_fetch_assoc($res)) {
return $row['barcode'];
} else {
return 0;
}
}
Update if you need to search by barcode you can create another function:
function itemProduct($barcode) {
$sql = "SELECT ProductId, Barcode FROM Products WHERE Barcode = $barcode ";
$res = mysql_query($sql);
if ($row = mysql_fetch_assoc($res)) {
return $row['ProductId'];
} else {
return 0;
}
}
Sounds like you are missing an index on your Barcode column in your database.. A single row lookup using a presumably unique single indexed column should be blisteringly fast.
CREATE INDEX Barcode_Index ON Products (Barcode)
Then simply:
SELECT ProductId FROM Products WHERE Barcode = *INPUT*
You could also make the index UNIQUE if you NULL the Barcode where they currently = '' if there are more than one of these.
Another option is keying the array you have with the Barcode:
while ($rijen = mysql_fetch_assoc($res)) {
$GLOBALS['arrBarcodes'][$rijen['Barcode']] = $rijen;
}
or even just:
while ($rijen = mysql_fetch_assoc($res)) {
$GLOBALS['arrBarcodes'][$rijen['Barcode']] = $rijen['ProductId'];
}
Then you can do a straight look up:
$ProductId = isset($GLOBALS['arrBarcodes'][$Barcode])
?$GLOBALS['arrBarcodes'][$Barcode]['ProductId']
:0;
or:
$ProductId = isset($GLOBALS['arrBarcodes'][$Barcode])
?$GLOBALS['arrBarcodes'][$Barcode]
:0;
N.B Please read the warnings in the comments about use of $GLOBALS and mysql_query.
If you need it, store the barcodes array in an object or variable instead.
PDO is pretty handy, and I think it can also key your returned array for you on fetch.
I have a query in which I am tring to put the results in an array.
The query returns all data of the two tables: order and orderdetails:
SELECT orders.*, order_details.* FROM `webshop_orders`
LEFT JOIN `order_details`
ON `orders`.`order_id` = `order_details`.`f_order_id`
WHERE `orders`.`f_site_id` = $iSite_id AND `orders`.`order_id` = $iOrder_id;";
I am trying to found out how to return this data an put them in an array of the following format:
$aOrders = array(
0=>array(Orders.parameter1=>value, orders.parameter2=>value, orders.parameter3=>value, 'orderdetails'=>array(
array(Orderdetails.parameter1=>value, orderdetails.parameter2=>value)));
I currently return every result as an associate array and manually split every variable based on its name using 2 key-arrays, but this seems very 'labor-intensive'?
while($aResults = mysql_fetch_assoc($aResult)) {
$i++;
foreach($aResults as $sKey=>$mValue){
if(in_array($sKey, $aOrderKeys){
$aOrder[$i][$sKey] = $mValue;
} else {
$aOrder[$i]['orderdetails'][$sKey] = $mValue;
}
}
}
EDIT: the function above does not take multiple order-details into consideration, but the function is meant as an example!
Is there an easier way or can I use a better query for this?
You can use the following while loop to fill your array:
$data = array();
while ($row = mysql_fetch_assoc($result)) {
if (!isset($data[$row['order_id']])) {
$order = array('order_id' => $row['order_id'],
'order_date' => $row['order_date'],
/* ... */
'orderdetails' => array());
$data[$row['order_id']] = $order;
}
if (isset($row['order_details_id'])) { // or is it "!= null"? don't know...
$details = array('id' => $row['order_details_id'],
'whatever' => $row['order_details_whatever']);
$data[$row['order_id']]['orderdetails'][] = $details;
}
}
This way you can have multiple orderdetails for one order, they get all added to the ['orderdetails'] field.
Additional notes:
Do not use SELECT *, see the question What is the reason not to use select *? and any other website about this topic.
Do not use the mysql_*() functions (even though I did above for showing the while loop), they are deprecated. Use PDO instead.
I have this table: TABLE_ELEMENTS, with the name ELEMENTS, i have a multiple values inside, see image.
This is the php and return the results from autocomplete request.
$("#autocomplete").autocomplete({
source: "http://localhost/include/autocomplete.php?type=mauto_complete",
First i call this..
if(isset($_GET['type']) && in_array($_GET['type'], $arr_action)) $type=$_GET['type'];
if($type == "mauto_complete") {
require_once $config_abs_path."/autocomplete/autocomplete.php";
if(isset($_GET['term'])) {
$term = escape($_GET['term']);
$response = mauto_complete::getAutocomplete($term);
echo json_encode($response);
}
}
And this is the secondauto.php file
function getAutocomplete($term) {
global $db;
global $config_table_prefix;
global $crt_lang;
$elements=$db->fetchRow("select Distinct `elements` from TABLE_ELEMENTS where `elements` like '$term%' limit 10");
$elements_array = explode("|", $elements);
return $elements_array;
}
I have write this after select
$elements_array = explode("|", $elements);
Ok the request is working fine, but in autocomplete results when i type the word Building i take no words.
But when i type the first word of the elements ( Apartment ) i take all words.
The words is not uniqe
A common approach to this is to add a | to the left of the field, then search that. This ensures that an element containing the search doesn't get matched.
select
Distinct `elements`
from
TABLE_ELEMENTS
where
lower(CONCAT('|', `elements`)) LIKE lower('%|$term%')
However, you're probably looking for something else. Below is how I'd approach it. I couldn't figure out what library you were using for your connection, so you may have to change a little bit for it to work for you.
function getAutocomplete($name, $term)
{
// make sure you escape the string to avoid SQL injection
$name = mysqli_real_escape_string($db, $name);
// make the searches case-insensitive
$term = strtolower($term);
// fetch the valid elements for the field and split them using explode
$elements = $db->fetchRow("SELECT `elements` FROM `TABLE_ELEMENTS` WHERE `name` = '$name'");
$elements_array = explode('|', $elements);
// make an array to save the matching elements
$filtered = array();
// iterate over each element to check for a match
foreach($elements_array as $element)
{
// check to see if the beginning of the element starts with the search term
if(strpos(strtolower($element), $term) === 0)
{
// add it to the filtered array
$filtered[] = $element;
}
}
// return the matching results
return $filtered;
}
Then to use it, specify what field you want to autocomplete for:
print_r(getAutocomplete('Property Type', 'B'));
// Outputs: Array
// (
// [0] => Building
// [1] => Bungalow
// [2] => Business
// )
To make your existing code to use it, change your JavaScript to match the following. You'll need to change name depending on what field you're autocompleting.
$("#autocomplete").autocomplete({
source: "http://localhost/include/autocomplete.php?type=mauto_complete&name=Property%20Type"
});
Then update the file where you call the getAutocomplete function:
if(isset($_GET['type']) && in_array($_GET['type'], $arr_action)) $type=$_GET['type'];
if($type == "mauto_complete") {
require_once $config_abs_path."/autocomplete/autocomplete.php";
if(isset($_GET['term']) && isset($_GET['name'])) {
$name = $_GET['name'];
$term = $_GET['term'];
$response = mauto_complete::getAutocomplete($name, $term);
echo json_encode($response);
}
}
Try use like this to get all possible results
$elements=$db->fetchRow("select distinct `elements` from TABLE_ELEMENTS where lower(`elements`) like lower('%$term%') limit 10");
i am using cakephp. and want to display all data in database in dropdown list. but it returns only last item. there is some problem in loop. my code is below.
foreach ($origions as $or);
$id = $or["origions"]["id"];
$orgn = $or["origions"]["origion"];
$options = array($id=>$orgn);
echo $this->Form->select('origions.origion', $options);
this display only last record in dropdown list. please help what to do that all data in table display over here.
Change it to,
$options = array();
foreach ($origions as $or){
$id = $or["origions"]["id"];
$orgn = $or["origions"]["origion"];
$options[$id] = $orgn;
}
echo $this->Form->select('origions.origion', $options);
For selected,
echo $this->Form->select('origions.origion', $options, array('value' => 'your_default_id'));
Reference.
OTHER WAY (more optimized code)...
You can set Your data $this->set from the controller.
From controller You can combine / extract / merge / sort / etc... multidimensional arrays like:
$result = Set::combine($origions, '{n}.origions.id', '{n}.origions.origion');
Read more about Cakephp SET::array functions http://book.cakephp.org/2.0/en/core-utility-libraries/set.html
how to format sql server rows using php that look like this:
id company value monthyear
1 companyone 30 january2012
2 companytwo 20 february2012
3 companyone 10 february2012
into this:
monthyear: ['january2012', 'february2012']
and this:
company: 'companyone', value: [30, 10]
company: 'companytwo', value: [0, 20]
each instance of a month from the db is combined into one instance.
company one, which has two rows, is combined into one instance where each value is lined up in order of the month. company two, which only has one instance, has it's value defined as 0 where it has no instance in a month.
the farthest i've gotten is are two two dimensional array with array_merge_recursive and some conditional statements but then my head goes into knots.
SELECT
company,
GROUP_CONCAT(value SEPARATOR ',') AS value,
GROUP_CONCAT(monthyear SEPARATOR ',') AS monthyear
FROM
yourTable
GROUP BY
company
Some Reference for GROUP_CONCAT.
PHP solution:
Select the to be grouped attribute sorted (company). Loop over them and open a new group every time you encounter a different value for company. As long as the current row has the same row as the previous, add value and monthyear to the current company.
You could do this even without sorting:
while($row = mysql_fetch_assoc($resource))
{
$values[$row["country"]][] = $row["value"];
$monthyear[$row["country"]][] = $row["monthyear"];
}
Some output example
foreach ($values as $country => $valuesOneCountry)
{
// each country
var_dump($country);
foreach ($valuesOneCountry as $i => $value)
{
// value, monthyear for each original row
var_dump($value, $monthyear[$country][$i]);
}
}
Elegant way with OOP:
class Tuple
{
public $country, $values, $monthyears;
public function __construct($country, $values = array(), $monthyears = array())
{
$this->country = $country;
$this->values = $value;
$this->monthyears = $monthyears;
}
}
$tuples = array();
while($row = mysql_fetch_assoc($resource))
{
if (!isset($tuples[$row["country"]]))
$tuples[$row["country"]] = new Tuple($row["country"]);
// save reference for easy access
$tuple = $tuples[$row["country"]];
// or some method like $tuple->addValue($row["value"]);
$tuple->values[] = $row["value"];
$tuple->monthyears[] = $row["monthyear"];
}
var_dump($tuples);