I've got a data schema like this:
cp
id te su
1 7 2
2 7 1
3 6 8
cl
id cp st
1 2 5
2 2 6
3 1 6
us
id na
.. ..
5 Joe
6 Mike
7 Tina
.. ..
I want to run a php function foo($te) with foo(7) to output data like this from mySQL
[0]
su: 1
st_list:
[0]
id:6
na:Mike
[1]
su: 2
st_list:
[0]
id:5
na:Joe
[1]
id:6
na:Mike
I want to know how best to do this. Right now I'm able to use JOINs, but the result looks like this
[0]
su: 1
st_id:6
st_na:Mike
[1]
su: 2
st_id:5
st_na:Joe
[3]
su: 2
id:6
na:Mike
The su:2 is repeated... obviously that isn't a problem in this example, the problem is that in the real thing that su represents a lot more data, that i'll be getting through "this" (whatever answer I choose) method.
EDIT:
I hope you understand what I'm asking... I know a lot of you guys are way more knowledgable in mySQL and development in general than me, so that's why i'm asking in such a plain (I HAVE THS----> WANT THIS) way, because I think if I asked any more specifically I would end up making assumptions about the way it should run). I want an effecient solution, because this data is being used to populate search results.
Thanks!!!!!!!!!!
You will need to loop over the results yourself and build the array in the format you want. MySQL can't give you the results in the nested format you want. Here's a rough draft (untested):
$su = 0;
$st_list = array();
$nested = array();
foreach ($results as $row) {
if ($su != 0 && $row['su'] != $su) {
$nested[] = compact('su', 'st_list');
}
if ($su != $row['su']) {
$su = $row['su'];
$st_list = array();
}
$st_list[] = array(
'id' => $row['st_id'],
'na' => $row['st_na'],
);
}
$nested[] = compact('su', 'st_list');
Edit: Usually it's best to simply fetch all the results you want using a single SQL query. That is almost always the most efficient way to do it. But if it really matters to you (and this is a performance critical part of your application), the only way to know for sure is benchmark both methods. A lot depends on your database layout, number of rows, SQL indexes, etcetera.
SELECT distinct us.id,na FROM cp
LEFT JOIN cl ON cp.su = cl.cp
LEFT JOIN us ON us.id = cl.st
where te = "7"
Does this provide the results you are looking for?
Alternately,
SELECT su,us.id,na FROM cp
LEFT JOIN cl ON cp.su = cl.cp
LEFT JOIN us ON us.id = cl.st
where te = "7"
ORDER BY su
Is closer to the formatting you asked for in your post.
In your model, you can have something like these too...
function get_te($te)
{
$qry = $this->db->get_where('cp', array('te' => $te));
$raw_te = $qry->result_array();
$te = array();
$i = 0;
while($i < count($raw_te))
{
$te[$i]['su'] = $raw_te[$i]['su'];
$qry = $this->db->select('*')
->from('cl')
->join('us', 'us.id = cl.id')
->where('cp', $raw_te[$i]['id'])
->get();
$te[$i]['st_list'] = $qry->result_array();
$i++;
}
return $te;
}
Related
First, thanks for any help.
I've spent countless hours on here and other forums trying to find my exact solution but either 1) I'm not understanding the one's I've read or 2)I haven't found the right answer.
In PHP, I've run a somewhat complex query which returns a set of records similar to:
id | name | direction|
1 aaa east
2 bbb west
3 ccc east
I've created an associative array such as:
$query=("select * from foo");
$result=mysql_query($query);
$array=mysql_fetch_assoc($result);
Now, what I need to do seems simple but I'm not grasping the concept for some reason.
I need to loop through the entire $array and return a count of any value that I want to specify and store that count in a variable.
i.e. Show me how many times east shows up in the "direction" column and put that in a variable called $eastcount.
I've tried various combinations of using foreach loops with incremental counts and have tried using array_count_values but have not been able to put the pieces together :/
// build query
$query=("select * from foo");
// execute query
$result=mysql_query($query);
// declare vars
$east_count = 0;
// iterate through results
while ($data = mysql_fetch_array($result)) {
// grab DIRECTION column value
$direction = $data['direction'];
// detect 'east'
if ($direction == 'east') {
// increment 'east' count
$east_count++;
}
}
// print # of times we had 'east'
echo("direction said 'east' $east_count times");
This should work (sorry for the lack of code block I'm on my iPhone).
http://www.php.net/manual/en/function.array-count-values.php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
Array
(
[1] => 2
[hello] => 2
[world] => 1
)
How about this:
query=("select * from foo");
$result=mysql_query($query);
$directions = array();
while($direction = mysql_fetch_assoc($result) {
$directions[] = $direction['direction'];
}
$directionCounts = array_count_values($directions);
//now you can access your counts like this:
echo $directionCounts['east'];
First, of all you should be using mysqli instead. But, anyhow I hope this makes some sense.
if ($result) {
$count = 0;
while ( $row = mysql_fetch_assoc($result)) {
if ($row["route"] === "east") {
$count += 1;
}
}
return $count;
}
I want to create a Array with multidimension arrays from a database. The Database has 3 tables, one for vehicle, one for damages and one for damagesPhotos.
Table vehicle has two columns id and name
Table damages has four columns damagesID, vehicleID, damagesType and damagesDescription.
Table damagesPhotos has three columns damagesPhotoID and damagesID and damagesPhotoUrl
I need to combine thoose three columns into an array, that looks like this:
$vehicle = array(
"id" => "somestring",
"name" => "somestring",
"damages" => array(
"damagesType" => "somestring",
"damagesDescription" => "somestring",
"photoOfDamages" => array(
"damagesPhotoUrl" => "somestring"
)
)
);
My code looks like this, but is not working the right way.
$result = mysql_query( "SELECT * from vehicle v LEFT JOIN damages d ON v.id = d.vehicleID LEFT JOIN damagesPhotos p ON d.damagesID = p.damagesID WHERE d.damagesID = p.damagesID AND v.id = 1") or die(mysql_error());
$rowsResult = array();
while ($r = mysql_fetch_assoc($result))
{
$rowsResult [] = $r;
}
mysql_free_result($result);
echo json_encode($rowsResult);
...
/Morten
As its not possible in mysql, so we can write a script which gives all information about specific vehicle and with that data, we can create an array.
Refer following code.
$query = "SELECT * from vehicle v LEFT JOIN damages d ON v.id = d.vehicleID LEFT JOIN damagesPhotos p ON d.damagesID = p.damagesID WHERE d.damagesID = p.damagesID AND v.id = 1";
$result = mysql_query($query);
$i = 0;
$vehicle = array();
while($row = mysql_fetch_array($result)){
$vehicle[$i] = array(
"id" => $row[id],
"name" => $row[name],
"damages" => array(
"damagesType" => $row[damagesType],
"damagesDescription" => $row[damagesDescription],
"photoOfDamages" => array(
"damagesPhotoUrl" => $row[damagesPhotoUrl]
)
)
);
$i++;
}
You can't get a multidimensional array from mysql, it just gives you a two dimensional resultset. A number of column values for each row is all you can get. If you want it nested like that, you'll have to process the array after retrieving the results.
Something like this:
$vehicles = array();
while ($r = mysql_fetch_assoc($result))
{
$vehicle['id'] = $r['id'];
...
$damage = array();
$damage['damagesType'] = $r['damagesType'];
...
$vehicle['damages'] = $damage;
...
array_push($vehicles, $vehicle);
}
echo json_encode($vehicles);
It is not possible to have MySQL do all the work for you here (well, it is possible to have it do most of the work, but don't) because a result set from MySQL - or any SQL driven database - can have exactly two dimensions. The first dimension is a collection of rows, and the second is a collection of columns for each row.
Based on the example target data structure, you have two choices:
Get the initial result set (vehicle LEFT JOIN damages) and iterate over it, running queries to get the photos
Join all tables together as you are currently doing and post-process it into the desired multidimensional structure.
It's a trade off - option 1 results in a lot more database traffic but retrieves no more than the required data, whereas option 2 reduces it to a single query with less database traffic, but retrieves more data than required because each photo row carries the entire vehicle's data with it.
Option 1 would be a prime candidate for using prepared statements, which is something you are unable to take advantage of using the mysql_* functions. You should switch to using PDO or MySQLi instead. I personally recommend PDO. There are numerous other reasons for doing this as well, including the fact that the MySQL extension will one day be removed from PHP, and the proper use of prepared statements can completely removed any risk of security problems resulting from SQL injection via user input.
I would probably recommend option 2.
Thanks to Vinay, my array looks like this. Thats nice :)
[{"vehilceId":"1",
"name":"AW55005",
"damages":{
"damagesType":"Exterior",
"damagesDescription":"Rust",
"photoOfDamages":{
"damagesPhotoUrl":"link to damagesPhoto 01"
}
}
},
{"vehilceId":"1",
"name":"AW55005",
"damages":{
"damagesType":"Exterior",
"damagesDescription":"Rust",
"photoOfDamages":{
"damagesPhotoUrl":"link to damagesPhoto 02"
}
}
},
{"vehilceId":"1",
"name":"AW55005",
"damages":{
"damagesType":"Interior",
"damagesDescription":"Scratch",
"photoOfDamages":{
"damagesPhotoUrl":"link to damagesPhoto 03"
}
}
}
But as you can see the first two objects are the same only the damagesPhotoUrl is different.
How do I merge thoose two array so it will look like this:
{"vehilceId":"1",
"name":"AW55005",
"damages":{
"damagesType":"Exterior",
"damagesDescription":"Rust",
"photoOfDamages":{
{"damagesPhotoUrl":"link to damagesPhoto 01"},
{"damagesPhotoUrl":"link to damagesPhoto 02"}
}
}
}, ...
/Morten
After solving you main problem. I am writing this for new problem. As I know, you cant assign values to same key in your array means you cant allow to have duplicate keys. Because How would you access the value you want if more than one can have the same key. That's why you can choose another way to do merge your value. Re-arrange your array in following way.
$key = "damagesPhotoUrl";
$value = "link to damagesPhoto 01";
$array[$key][] = $value;
you can then access it as:
echo $array[$key][0];
echo $array[$key][1];
Its very late.... but if you using PDO then PDO::FETCH_COLUMN with PDO::FETCH_GROUP can make result in 3 dimensional array.
I think its limited, I'm not very SQL guy, but saying "You can't get a multidimensional array from mysql...or any SQL driven database - can have exactly two dimensions" can be not quite true.
Sorry for my English and off topic (this question is about mysql, not pdo)
http://php.net/manual/en/pdostatement.fetchall.php
(pseudo array):
array(
array(//group 1
array(
0=>item1,
0=>item2...
)
array(
0=>item1,
0=>item2...
)
array(
0=>item1,
0=>item2...
)
array(
0=>item1,
0=>item2...
)
)...
array(//group 2
array(
0=>item1,
0=>item2...
)
array(
0=>item1,
0=>item2...
)
)...
)
ok, a bit of background,
just into codeigniter
not a fan of sql and server-side scripts
i know what joins are
i have a many-to-many database for the first time
it's because joins typically have the following example as a result. but i wanted to parse this without having to build code to ignore repetitions. it's a 3-table join sample. the issue of repeating values increases as i join more tables:
table1.authorid table1.authorname table2.books table3.favorited
1 john john's book 1 jean
1 john john's book 1 joe
1 john john's book 2 ken
1 john john's book 2 mark
2 mark mark's book 1 alice
2 mark mark's book 1 ted
2 mark mark's book 2 sarah
2 mark mark's book 2 denise
is there a way in codeigniter (or plain PHP) that i can get this array form and turn it into something like json (and parse it like json)
$result = [
{
'authorid':1,
'authorname':'john',
'books':['john's book1','john's book2'],
'favorited':['jean','joe','ken','mark']
},
{
'authorid':2,
'authorname':'mark',
'books':['mark's book1','mark's book2'],
'favorited':['alice','ted','sarah','denise']
}
]
Update: this is not limited to this depth of objects/arrays (like in the example). it can go deeper (arrays in arrays, arrays in objects, objects in arrays, objects in objects)
// first, we need the SQL results in the $result_array variable
$sql = 'SELECT ...'; // your SQL command
$result_array = $this->db->query($sql)->result_array(); // codeigniter code
// here the real answer begins
$result = array();
foreach ($result_array as $row)
{
if (!isset($result[$row['authorid']])
{
$author = new StdClass();
$author->authorid = $row['authorid'];
$author->authorname = $row['authorname'];
$author->books = array($row['books']);
$author->favorited = array($row['favorited']);
$result[$row['authorid']] = $author;
}
else
{
if (!in_array($row['books'], $result[$row['authorid']]->books))
{
$result[$row['authorid']]->books[] = $row['books'];
}
if (!in_array($row['favorited'], $result[$row['authorid']]->favorited))
{
$result[$row['authorid']]->favorited[] = $row['favorited'];
}
}
}
$result = array_values($result);
echo json_encode($result);
At this time I have this very complex query that I loop through and I get something like this:
List of Challenges:
TEAM A
- Challenge 1
TEAM A
- Challenge 4
TEAM A
- Challege 6
And I want to change to something like:
TEAM A
- Challenge 1
- Challenge 4
- Challenge 6
My question is, since the query is a very complex one, maybe I could do this inside the loop but, if that's the case, how can we achieve something like that?
Can I ask an example case so that I can use, in order to solve this issue?
Thanks a lot,
MEM
UPDATE:
The query is something like this:
Translated:
public function listachallengesPendentes()
{
$select = $this->getAdapter()->select();
$select->from(array("e"=>"teams"),array('name'));
$select->join(array("de"=>"challengeperteam"),"e.cod_team = de.cod_teamFk",array());
$select->join(array("d"=>"challenges"),"d.cod_challenge = de.cod_challengeFk",array('title'));
$select->columns(array("e.cod_team"
,"name_team"=>"e.name"
,"d.cod_challenge"
,"name_challenge"=>"d.title"
,"d.details"
,"d.score"
,"category"=>"d.cod_categoryFk"
,"de.proof"
,"de.date_concluded"
,"de.cod_challenge_team"
));
$select->where("de.status = 0");
$select->order(array('e.cod_team DESC', 'de.cod_challenge_team DESC'));
return $this->getAdapter()->fetchAll($select);
}
So I need to add a distinct some part :s :D ?
The foreach actually is pretty basic:
foreach ($challenges as $d){
//display the name:
echo $d['name_team'];
...
}
UPDATE 2
The clean query (not tested):
SELECT e.name
,d.cod_team
,d.cod_challenge
,d.title
,d.details
,d.score
,de.proof
,de.date_concluded
,de.cod_challenge_team
FROM teams e
INNER JOIN challengeperteam de ON de.cod_teamFk = e.cod_team
INNER JOIN challenges d ON d.cod_challenge = de.cod_challengeFk
WHERE de.status = 0
ORDER BY e.cod_team DESC, de.cod_challenge_team DESC;
Something along the lines of:
$current_team = null;
foreach($challenges as $challenge){
if($current_team != $challenge->team){
$current_team = $challenge->team;
echo $current_team, "\n";
}
echo $challenge->challenge_name, "\n";
}
At a very basic level, ie in the loop, you can just detect if the TEAM A variable is equal to the current (previous) value, and if so, don't print it a second time. This relies on the result set being sorted on the TEAM A column.
However, you can also do this in the SQL query, so if you can provide the current SQL Query, I can explain how you'd update it.
you could store the array results in a multi-dimensional array like so:
$query_Challenges = "SELECT `Team`,`Challenges` FROM YourTable";
$Challenges = mysql_query($query_Challenges, $dbconnection) or die(mysql_error());
$row_Challenges = mysql_fetch_assoc($Challenges);
$challengeResults = array();
do{
if(!array_key_exists($row_Challenges['cod_team'])){
$challengeResults[$row_Challenges['cod_team']] = array();
}
$challengeResults[$row_Challenges['cod_team']][] = $row_Challenges['cod_challenge_team'];
}while($row_Challenges = mysql_fetch_assoc($Challenges));
EDIT
looking at your query statement, the data should be already sorted properly by your ORDER clause, so if you just need not repeatedly print the team as shown in codeblock 2, then something like:
$team = '';
do {
if($team != $row_Challenges['cod_team']){
echo "TEAM $row_Challenges['cod_team']<br/>";
$team = $row_Challenges['cod_team'];
}
echo " - $row_Challenges['cod_challenge_team']<br />";
}while($row_Challenges = mysql_fetch_assoc($Challenges));
you could easily substitute a foreach for the do loop, as long as there is a variable used as the "current team" and an if statement used to say "dont print the next team name unless its different than the current team name"
Ok so basically my code isnt working as intended.. so i took it completely apart and even placed this query at the top of page; tried hardcoding in values and its still not working. This particular query is supposed to return 5 rows of data to the $weapons array, but its not working.
$weapons_sql = "SELECT weapon_id, weapon_name, weapon_strength FROM Weapon_Info WHERE weapon_id BETWEEN 1 AND 5";
$weapons_query = mysql_query($weapons_sql);
$weapons = mysql_fetch_array($weapons_query);
print_r($weapons);
so weapon_id in the databse is a smallint(8) or something rather, (exact length im unsure of atm).. and it has 30 rows in the table, weapon_id ranging from 1-30
this particular snippet when run returns:
Array ( [0] => 1 [weapon_id] => 1 [1] => Humvee [weapon_name] => Humvee [2] => 100 [weapon_strength] => 100 )
I just don't understand it.. every other query in my entire project works save this one. Please help? I've also tried replacing BETWEEN operator with >= <= operators, which outputs the same results.
try
while($weapons = mysql_fetch_array($weapons_query)){
print_r($weapons);
}
you need a loop like this to see all rows.
You are only fetching one row of the results. You need to loop through and collect all the results:
while(false !== ($row = mysql_fetch_array($weapons_query))) {
$weapons[] = $row;
}
var_dump($weapons);
mysql_fetch_array only fetches one row of results at a time, as shown in the documentation. This means, for instance, that you can deal with sets of results that demand more memory than your script is allowed.
mysql_fetch_array returns only one row. You want to keep fetching arrays until you have all the rows:
$weapons_sql = "SELECT weapon_id, weapon_name, weapon_strength FROM Weapon_Info WHERE weapon_id BETWEEN 1 AND 5";
$weapons_query = mysql_query($weapons_sql);
$weapons = array();
while ($weapon = mysql_fetch_array($weapons_query))
{
$weapons[] = $weapon;
}
print_r($weapons);