Combine array items by name with a separator? - php

I have the following PHP code which runs a MySQL query and returns the results as an array:
function mysql_resultTo2DAssocArray ( $result) {
$i=0;
$ret = array();
while ($row = mysql_fetch_assoc($result)) {
foreach ($row as $key => $value) {
$ret[$i][$key] = $value;
}
$i++;
}
return ($ret);
}
$compare = mysql_resultTo2DAssocArray(mysql_query("SELECT Temp.School, Temp.Status, Snow.Token FROM Temp
JOIN Snow ON Temp.School = Snow.School"));
The results of this look like:
Array
(
[0] => Array
(
[School] => School Name 1
[Status] => Delayed Two Hours
[Token] => Token1
)
[1] => Array
(
[School] => School Name 1
[Status] => Delayed Two Hours
[Token] => Token2
)
)
Is it possible to combine the Token items by a comma within those arrays if the School item is the same for each?
One thing is that it's possible for there to be more arrays within the global array, with different School names, that shouldn't be grouped but left alone. Basically, is it possible to ONLY group when School is the same. It's also possible for there to be more than two tokens.

SELECT Temp.School, Temp.Status, GROUP_CONCAT(Snow.Token) Tokens
FROM Temp JOIN Snow USING (School)
GROUP BY Temp.School
This isn't completely valid, because the Status column is not aggregated or part of the GROUP BY; however MySQL normally allows it (there's an option to disallow it, I don't remember the name offhand). If there are rows with different Status values, it will pick one of them arbitrarily; you didn't say what should happen with different Statuses.

Related

Joining arrays in PHP (like MySQL join)

I would like to join two arrays in PHP, the same as I could do with MySQL join left. I have two arrays:
$db_products from database (it has id and sku fields)
$csv_prices from a CSV file (it has sku and price fields)
$db_products: (it has 4000 items)
Array
(
[0] => Array
(
[id] => 1012
[sku] => asd123
)
[N] => Array
(
[id] => ...
[sku] => ...
)
)
$csv_prices: (it has 8000 items)
Array
(
[0] => Array
(
[sku] => asd123
[price] => 15.50
)
[N] => Array
(
[sku] => ...
[price] => ...
)
)
The join is $db_products[$key][sku] = $csv_prices[$key][sku]. To find the matching pair, I am doing loops in loops which result in 4000 * 8000 check for match. It consumes a lot of energy and time, and I want to be more efficient.
I could lower by 10% the used time, by unset()-ing the used $csv_prices[$key], but I want to be more efficient.
If you loop through the $csv_products array once and set the SKU as the array key then you won't have to exponentially loop through that array each time you have a new product to find its match.
Instead, you just loop through the product array and use isset() to see if it exists or not.
This way you'll only need to do 1x count($db_products) and 1x count($csv_prices) repetitions, instead of count($db_products) * count($csv_prices) reps (12 thousand vs 32 million).
The concept could be considered to be similar to indexing in databases - you use the key you want to look up as the array key/index, meaning you don't have to loop through the array every time to find the record you want.
Example:
// Reindex the CSV array to use SKU as the key
$reindexed = array();
foreach ($csv_prices as $values) {
$reindexed[$values['sku']] = $values;
}
unset($csv_prices);
// Join the prices
foreach ($db_products as &$product) {
$sku = $product['sku'];
$product['price'] = isset($reindexed[$sku]) ? $reindexed[$sku]['price'] : '';
}
Of course, you won't see a remarkable difference in performance until you start using large data sets - the change would be noticeable exponentially as the data sets grow.
This is working fine for me
function left_join_arrays($key, $array1, $array2) {
$i=0;
foreach ($array1 as $arr1) {
foreach ($array2 as $arr2) {
if ($arr1[$key]==$arr2[$key]) {
foreach(array_keys($arr2) as $key2){
if ($key != $key2) {
$array1[$i][$key2]=$arr2[$key2];
}
}
continue;
}
}
$i++;
}
return $array1;
}

Show Can I pull Each Of These Out Of An Array?

I am having trouble pulling elements out of this multi-dimensional array?
Here is my code below:
$ShowTables = $Con->prepare("SHOW TABLES");
$ShowTables->execute();
$ShowTResults = $ShowTables->fetchAll();
If I print_r($ShowTResults); I get this multi-dimensional array:
Array (
[0] => Array ( [Tables_in_alltables] => userinformation [0] => userinformation )
[1] => Array ( [Tables_in_alltables] => users [0] => users )
)
Foreach new table is loaded it adds another dimension of the array. I want to pull each of the table names, out of the multi-dimensional array into a new array which I can use for future plans.
Would anyone have any ideas?
I have tried 1 foreach Loop; but this served no justice.
You want to fetch all results of the first column in form of an array:
$ShowTResults = $Con->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN, 0);
print_r($ShowTResults);
This gives you:
Array (
[0] => userinformation
[1] => users
)
Which I think is what you're looking for.
Another variant (a bit more complicated, but fitting for similar but little different cases) is to fetch the results as function (PDO::FETCH_FUNC) and directly map the result:
$ShowTResults = $ShowTables->fetchAll(PDO::FETCH_FUNC, function($table) {
return $table;
});
A Solution I tried: Perhaps not as other will do, which is in full respect. But Here is mine:
$DatabaseTables = array();
foreach($ShowTResults AS $ShowTResult)
{
foreach ($ShowTResult AS $ShowT)
{
$DatabaseTables[] = $ShowT;
}
}
$DatabaseTables = array_unique($DatabaseTables); //Deletes Duplicates in Array
unset($ShowTResult);
unset($ShowT); // Free up these variables
print_r($DatabaseTables);

How to group events from different queries together in an array by time

I am pulling out a number of notes associated with a time from my database.
I'm not too hot with multidimensional arrays, but I'd like to group all the events together under the time that they occurred.
Here is one of my queries:
SELECT TIME(date) AS time, followupNote, completed, entityRef
FROM entity_followups
WHERE userRef = ?
AND DAY(date) = ?
AND MONTH(date) = ?
AND YEAR(date) = ?
An example output from this could be three rows, the first column being the time, then the note, completed, then the entityRef.
I want any rows with the same time to be grouped together in the array, e.g.
Array (
[0] => Array (
[0] => 12:00:00
[1] => Array (
[0] => note
[1] => completed
[2] => entityRef
)
[2] => Array (
[0] => note2
[1] => completed2
[2] => entityRef2
)
)
)
But later on there will be other queries that collect other kinds of events which need to be added into the top level array, and if an event has the same time as one in the subarray, it needs to be added into that.
I'll assume that your existing code is enough for getting the time and value. Thus you will have these items in whatever variable or data structure you choose to use. For the purposes of this answer, I will assume these values already exist in the individual variables: $time, $value[0], $value[1], and $value[2]. Further, I will assume that the results are being loaded into the array $timesAndValues[]
I think the key is to have the $timesAndValues[] array indexed on the corresponding time:
if (isset($timesAndValues[$time]))
{ //The corresponding sub-array already exists, so we just need to load it
//Push the array of values into the sub-array
array_push($timesAndValues[$time], $value);
}
else
{ //The corresponding sub-array does not exist yet, so we need to create it and load it
//Create the sub-array
$timesAndValues[$time] = array($time);
//Push the array of values into the sub-array
array_push($timesAndValues[$time], $value);
}

How do I organize two mysql tables into one big multidimensional array?

I'm having a hard time figuring this out...
I have two tables... ticket_winners, and tickets
in the ticket_winners table, usernames / profile information...
the tickets table is all of the tickets these users have for one userID, there could be 10+ tickets for each user in this table.
Question: How can I loop through the second iteration of data when the table tickets has more than 1 row for each user
function pullTickets() {
$sql = $this->mysql->retrieve("SELECT * FROM ticket_winners ORDER BY id DESC LIMIT 5");
$sql2 = $this->mysql->retrieve("SELECT id, userId, ticketId FROM tickets ORDER BY id ASC LIMIT 5");
while($row = mysql_fetch_array($sql)) {
$results[$row['id']]['user'] = $row['userId'];
while($row2 = mysql_fetch_array($sql2)) {
if($results[$row['id']]['user'] == $row2['userId']) {
$results[$row['id']]['tickets'][$row2['id']] = $row2['ticketId'];
} else {
}
}
}
return $results;
}
PHP page example: works fine
$data = $obj->pullTickets();
foreach($data as $user) {
echo $user['username'];
foreach($data['ticket'] as $ticket) {
echo $ticket['ticketId'];
}
}
What the array looks like now:
[1] => Array
(
[batch] => 1
[userId] => 200
[userName] => Craig
[tickets] => Array
(
[1] => GH7JNm72hN
[2] => JudM3rT3is
[3] => KiLPoXCmDF
)
)
[2] => Array
(
[batch] => 1
[userId] => 100
[userName] => Hewbie
needs to continue looping
)
the tickets table isn't being looped through each user like in the [1] array. It skips all the other users' tickets.
Try a left join on the ticket_winners table, don't use SELECT *, it is bad practice to do so and when using joins you should append each column with the table name.
SELECT tw.id,tw.userid,t,userName,t.id AS tick_id, t.ticketId
FROM `ticket_winners` AS tw
LEFT JOIN `tickets` AS t
ON tw.userid = t.userid
ORDER BY tw.id DESC LIMIT 5
The left join preserves the table format of your ticket winners table and will append t.id (in the output as tick_id),ticketId and userName.
This will give you an array consisting of multiple users, sorting them in one while loop will not be difficult as you simply create a winners array with the key of the usersid, within that array append the winning ticket id.
$results = array();
while ($sql = mysql_fetch_array($query, MYSQL_ASSOC) {
$results[$sql['userid']]['userName'] = $sql['user'];
$results[$sql['userid']]['tickets'][] = $sql['tick_id'];
}
The resulting array:
[1] => array
(
['userName'] => 'Craig',
['tickets'] => array
(
[0] => 'GH7JNm72hN',
[1] => 'JudM3rT3is'
)
)
[2] => array
(
['userName'] => 'Adam',
['tickets'] => array
(
[0] => 'GfdT24sDgC'
)
)
This eliminates the need to a) run two seperate queries, and b) avoid creating an uneccesary while loop within a while loop speeding this process up.
A good practice to follow when doing this is:
Get as much data in one query as possible.
Loop through once and sort data into one or multiple arrays eliminating duplications due to joins.
Your data is, as I see, applied to the $result array - both the tickets-data and the tickets_winner-data. What is your question then? Maybe I have totally misunderstood it.

Need an Array Count On Common Values

I am Using PHP and Mysql, Apachhe
I Have an Array
Array
(
[2] => Array
(
[0] => 6
[1] => 2
)
[1] => Array
(
[0] => 6
[1] => 2
)
)
Here The middle container is the Document ID and the final children are userids, Here I am looking for a way to find a method to count the common user ids among all the different Documents. I also need it specified that a particular user id available in which documentids...
could Some one guide me to achieve this?
Thanks in Advance,
OM
$unique_users = array();
foreach ($docs as $doc_id => $users)
{
foreach ($users as $user_id)
{
if (!isset($unique_users[$user_id]))
$unique_users[$user_id] = array($doc_id);
else
$unique_users[$user_id][] = $doc_id;
}
}
echo count($unique_users); // number of users
var_dump($unique_users[1]); // list of documents user_id #1 is in
Add all the ids from the first element to an array. Then continue to loop through the other elements and keep only the ids that are also in the current element.

Categories