sorting a result mysql/php - php

Lets say i have a list full of phones.
It's easy to print all the phones out in a unordered list like:
$get_phones = $mysqli->query("
SELECT
a.id,
b.phone_id,
a.phonename AS pname,
b.modelname AS mname,
FROM phone_brands
a LEFT OUTER JOIN phone_models b
ON a.id = b.phone_id");
while($phones = $get_phones->fetch_assoc()){
echo $phones['pname'] . $phones['mname'];}
But how can i make the list more readable by sorting all the models and phones like:
Iphone
3G
3GS
4G
Nokia
Lumia 1020
Lumia 925
Lumia 520
My guess is that i should do something like:
if($phones['pname'] == $phones['pname']{}
But i don't know if i'm far away here? Any help would be appreciated :)

Well ofcourse you could order the query by mname:
$get_phones = $mysqli->query("
SELECT
a.id,
b.phone_id,
a.phonename AS pname,
b.modelname AS mname,
FROM phone_brands
a LEFT OUTER JOIN phone_models b
ON a.id = b.phone_id
ORDER BY mname");
And then in php do something like:
$currentModel = "";
while($phones = $get_phones->fetch_assoc()){
if($currentModel != $phones['mname']){
echo $phones['mname'].'<br/>';
$currentModel = $phones['mname'];
}
echo $phones['pname'];
}

Sorting on the database level is much faster and at the end, the result is the same. You can just read it in a PHP array and have it sorted.
$get_phones = $mysqli->query("
SELECT
a.id,
b.phone_id,
a.phonename AS pname,
b.modelname AS mname,
FROM phone_brands
a LEFT OUTER JOIN phone_models b
ON a.id = b.phone_id
order by pname, mname");

SELECT
a.id,
b.phone_id,
a.phonename AS pname,
b.modelname AS mname,
FROM phone_brands AS a
LEFT OUTER JOIN phone_models AS b
ON a.id = b.phone_id
ORDER BY pname, mname DESC
That should do the job from what your question asks?
[edit]
I need to improve the code, i'm thinking using something like a foreach so it's more useable later than just order by :P – Simon Duun
Going on that comment, you could still use the order by in the query but do something like:
$phone_array = array();
while($phones = $get_phones->fetch_assoc()){
$phone_array[$phones['pname']] = $phones['pname'] . $phones['mname'];
}
ksort($phone_array);
foreach($phone_array as $phone_pname => $phone_value){
echo $phone_pname . ' -> ' . $phone_value . "\r\n";
}

Related

Codeigniter query generating multiple rows

Codeigniter:
public function get_customers(){
$this->db->select('*,customer.ID as ID,customer.Create_date as Create_date,transport.Name as Transporter, state.Name as State, city.Name as City, area.Name as Area, shipping_state.Name as Shipping_state, shipping_city.Name as Shipping_city, shipping_area.Name as Shipping_area');
$this->db->from('customer');
$this->db->join('transport','transport.ID = customer.Transporter','LEFT');
$this->db->join('state','state.ID = customer.State','LEFT');
$this->db->join('state as shipping_state','state.ID = customer.Shipping_state','LEFT');
$this->db->join('city','city.ID = customer.City','LEFT');
$this->db->join('city as shipping_city','city.ID = customer.Shipping_city','LEFT');
$this->db->join('area','area.ID = customer.Area','LEFT');
$this->db->join('area as shipping_area','area.ID = customer.Shipping_area','LEFT');
return $this->db->get()->result_array();
}
In customer table, there are 2 columns joining to the same table. in the customer table, there are only 1 rows. but when the query is generating it generating 1000+ rows. Anyone can please help me why it generating 1000+ rows and How can I resolve it.
You can always use $this->db->last_query() to visually understand and debug your code. It's good to do this, as you then you can start to understand how Active Record works.
$results = $this->db->get()->result_array();
log_message( "debug", "get_customers sql: ". $this->db->last_query() );
return $results;
So when you see your query in raw format; it looks like this:
SELECT
*,customer.ID as ID,
customer.Create_date as Create_date,
transport.Name as Transporter,
state.Name as State,
city.Name as City,
area.Name as Area,
shipping_state.Name as Shipping_state,
shipping_city.Name as Shipping_city,
shipping_area.Name as Shipping_area
FROM
customer
LEFT JOIN transport ON (
transport.ID = customer.Transporter
)
LEFT JOIN state ON (
state.ID = customer.State
)
LEFT JOIN state as shipping_state ON (
state.ID = customer.Shipping_state
)
LEFT JOIN city as shipping_state ON (
city.ID = customer.City
)
LEFT JOIN city as shipping_city ON (
city.ID = customer.Shipping_city
)
LEFT JOIN area ON (
area.ID = customer.Area
)
LEFT JOIN area as shipping_area ON (
area.ID = customer.Shipping_area
)
There's so many left joins here; that it will repeat any matched rows on each left join. It's hard to say without knowing the data, but it would appear that you would prefer to use a Hard Join.
With the amount of joins you have you might have to add a group by
so before your get add:
$this->db->group_by('customer.ID');

How to get all the data from mysql using PHP

As you can see inside my while loop i declare i variable $TYPES..
This is my first Query
$first = "SELECT DISTINCT DATE_FORMAT(z.DatePaid,'%M %d, %Y') AS Paid
FROM tblStudPayments z
INNER JOIN tblPersonalData p ON p.StudNo=z.StudNo
WHERE z.StudNo=p.StudNo AND z.SY='".$SY."' AND z.Sem='".$Sem."' ORDER BY z.DatePaid;";
$fs = safe_query($first);
$numrows = mysql_num_rows($fs);
if($numrows>0)
{
while($dataf = mysql_fetch_assoc($fs))
{
$types =$dataf['Paid'];
}
}
I wanted to pass the value of $TYPES to my second Query
And This is my Second Query
$sql="SELECT DISTINCT p.StudNo, p.LName, p.FName, p.MName, p.NName, c.Description, p.YearLevel, d.Status,
'".$types."' AS DateEnlisted,
FROM tblPersonalData p
INNER JOIN tblStudPayments sp ON sp.StudNo=p.StudNo AND sp.SY='".$SY."' AND sp.Sem='".$Sem."'
INNER JOIN tblStatusHistory d ON d.StudNo=sp.StudNo AND d.SY=sp.SY AND d.Sem=sp.Sem
INNER JOIN tblCourses c ON c.CourseCode=d.CourseCode AND c.HSOrCollege='".$dType."'
INNER JOIN tblUserAcct u ON u.UserName=p.StudNo
";
$sql.=" HAVING DateEnlisted = '".$a['DateEnrolled']."' ";
$sql.=" ORDER BY p.StudNo ASC;";
At the bottom of SELECT Statement you can see my variable $TYPES i get it from my first query.
The problem is it doesn't get all the data.. it only get the last data from mysql
Thanks in Advance..
[Image Suggested by Kundu Updated][1]
[Image Suggested by Kundu echo $sql][2]
i try one query but the loading of data takes 10-15MIN.
Put the 2nd query inside the 1st query while loop
In your while loop you put the value in a variable & evry time this variable is updated.So at the end of the loop it will return last type value. Either put it in a array, so it will store all the value.But that case you need to convert the array into string when you put it in 2nd query.Also make sure when you put value in $type it should be unique.
update your code like this:
$types=array();
while($dataf = mysql_fetch_assoc($fs))
{
$types[] = $dataf['Paid'];
}
$allTypes = implode(",`", array_unique($types));
Now in your query:
$sql="SELECT DISTINCT p.StudNo, p.LName, p.FName, p.MName, p.NName, c.Description, p.YearLevel, d.Status,
`".$allTypes."` AS DateEnlisted,
FROM tblPersonalData p
INNER JOIN tblStudPayments sp ON sp.StudNo=p.StudNo AND sp.SY='".$SY."' AND sp.Sem='".$Sem."'
INNER JOIN tblStatusHistory d ON d.StudNo=sp.StudNo AND d.SY=sp.SY AND d.Sem=sp.Sem
INNER JOIN tblCourses c ON c.CourseCode=d.CourseCode AND c.HSOrCollege='".$dType."'
INNER JOIN tblUserAcct u ON u.UserName=p.StudNo
";

My MySQLi query gives error but i can't find out thats wrong with it

I'm working with a mysql query to select data from multiple tables using LEFT OUTER JOIN. Now i get the following error when i exequte the query:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'wg.werkbon_global_id = wk.werkbon_klant_globalid LEFT OUTER
JOIN users AS u' at line 16
Only the problem is that i can't find out what's wrong with my query.
PHP Query:
$query = '
SELECT
wg.werkbon_global_id AS id,
wg.werkbon_global_status AS status,
wg.werkbon_global_date_lastedit AS date,
usr.user_firstname AS monteur_vn,
usr.user_insertion AS monteur_tv,
usr.user_lastname AS monteur_an,
wg.werkbon_global_type AS type,
wg.werkbon_global_layout AS layout,
wg.werkbon_global_werkzaamheden AS werkzaamheden,
wg.werkbon_global_opmerkingen AS opmerkingen,
wk.werkbon_klant_nummer AS klantnr
FROM
werkbon_klant AS wk
LEFT OUTER JOIN werkbon_global AS wg
wg.werkbon_global_id = wk.werkbon_klant_globalid
LEFT OUTER JOIN users AS usr
usr.user_id = wg.werkbon_global_monteur_finish
WHERE
wk.werkbon_klant_nummer = '.$db->Quote($klantid).'
ORDER BY id ASC;
$result = $db->loadAssoc($query);
I think my problem has something todo with left outer join but what?
You are missing the ON operator in your joins!
The correct syntax for a join is:
SELECT * FROM x LEFT JOIN y ON condition WHERE...
$query = "
SELECT
wg.werkbon_global_id AS id,
wg.werkbon_global_status AS status,
wg.werkbon_global_date_lastedit AS date,
usr.user_firstname AS monteur_vn,
usr.user_insertion AS monteur_tv,
usr.user_lastname AS monteur_an,
wg.werkbon_global_type AS type,
wg.werkbon_global_layout AS layout,
wg.werkbon_global_werkzaamheden AS werkzaamheden,
wg.werkbon_global_opmerkingen AS opmerkingen,
wk.werkbon_klant_nummer AS klantnr
FROM
werkbon_klant AS wk
LEFT OUTER JOIN werkbon_global AS wg
wg.werkbon_global_id = wk.werkbon_klant_globalid
LEFT OUTER JOIN users AS usr
usr.user_id = wg.werkbon_global_monteur_finish
WHERE
wk.werkbon_klant_nummer = '.$db->Quote($klantid).'
ORDER BY id ASC";
$result = $db->loadAssoc($query);
Make sure there isn't missing quote
Problem soved thanks to arkascha
The fixed query is now:
$query = '
SELECT
wg.werkbon_global_id AS id,
wg.werkbon_global_status AS status,
wg.werkbon_global_date_lastedit AS date,
usr.user_firstname AS monteur_vn,
usr.user_insertion AS monteur_tv,
usr.user_lastname AS monteur_an,
wg.werkbon_global_type AS type,
wg.werkbon_global_layout AS layout,
wg.werkbon_global_werkzaamheden AS werkzaamheden,
wg.werkbon_global_opmerkingen AS opmerkingen,
wk.werkbon_klant_nummer AS klantnr
FROM
werkbon_klant AS wk
LEFT OUTER JOIN werkbon_global AS wg ON
wg.werkbon_global_id = wk.werkbon_klant_globalid
LEFT OUTER JOIN users AS usr ON
usr.user_id = wg.werkbon_global_monteur_finish
WHERE
wk.werkbon_klant_nummer = '.$db->Quote($klantid).'
ORDER BY id ASC';
$result = $db->loadAssoc($query);
#fred i don't need to add quotes by column names. You only need to add quotes by string/blob values.
#johny my $db->Quote() function will add qoutes automaticly. I don't need to add them and put everything in quote's.
Thanks all for help.

MySQL joins: how to simplyfy the given query?

$sql="SELECT advertiser_name from broker_blocked_advertisers where pline=".$pLine." AND bid=".$cNr;
$result=mysqli_query($conn,$sql);
if(mysqli_num_rows($result)>0){
while($row=mysqli_fetch_array($result)){
$s=trim($row['advertiser_name']);
$sql2= "SELECT clientid from rv_clients where clientname='{$s}'";
$result2=mysqli_query($dbc,$sql2);
while($row2=mysqli_fetch_array($result2)){
$sql3= "SELECT campaignid from rv_campaigns where clientid=".$row2['clientid'];
$result3=mysqli_query($dbc,$sql3);
while($row3=mysqli_fetch_array($result3)){
$sql4= "SELECT bannerid from rv_banners where campaignid=".$row3['campaignid'];
$result4=mysqli_query($dbc,$sql4);
while($row4=mysqli_fetch_array($result4)){
$block_adr[]= $row4['bannerid'];
}
}
}
}
}
Anybody please suggest me to simplify the above code in a single query???.
The above code is really a wrong approach i think, please help how to short it out?.
Code description: Here i get one value from a sql table and by using that value i step forward to another query and so on.
Thanks in advance
Revised query and script:-
$sql = "SELECT d.bannerid
FROM broker_blocked_advertisers a
INNER JOIN rv_clients b ON a.advertiser_name = b.clientname
INNER JOIN rv_campaigns c ON b.clientid = c.clientid
INNER JOIN rv_banners d ON c.campaignid = d.ampaignid
WHERE a.pline=".$pLine." AND a.bid=".$cNr;
$result=mysqli_query($dbc,$sql);
while($row=mysqli_fetch_array($result))
{
$block_adr[]= $row['bannerid'];
}
This is the dreaded (n+1) latency death, four times over.
Every iteration through a loop is another network roundtrip. That's going to kill your performance.
Think "join". Bring all the data back in one round trip and sort it out on the client side.
Here's a simplified example:
select *
from campaign
join banner
on campaign.id = banner.campaign_id
That saves looping over campaigns.
All in one query
$sql="SELECT
bann.bannerid,camp.campaignid,c.clientid,b.advertiser_name as advname
from
broker_blocked_advertisers as b,
rv_clients as c,
rv_campaigns as camp,
rv_banners as bann
where b.pline=".$pLine."
AND bid=".$cNr."
AND c.clientname=advname.advertisername
AND camp.clientid=c.clientid
AND bann.campaign_id=camp.campaig_id"
YOU CAN USE A SINGLE QUERY LIKE THIS:
SELECT bannerid from rv_banners where campaignid=
(
SELECT campaignid from rv_campaigns where clientid=
(
SELECT clientid from rv_clients where clientname=
(
SELECT advertiser_name from broker_blocked_advertisers where pline=".$pLine."
AND bid=".$cNr;
)
)
);
SELECT "bannerId" FROM rv_banners A, rv_campaigns B, rv_clients C, broker_blocked_advertisers D
WHERE A.campaignid = B.campaignid AND B.clientid = C.clientname AND C.clientname = D.advertisername AND D.pline = ".$pline." AND D.bid = ".$cNr;

PHP while loop returning only one row when SUM added to multiple JOIN query

I have a query like this:
$query = "SELECT a.sender_id,
a.recipient_id,
a.form_id, due_date,
a.completed,
f.name,
p.priority,
u.first_name,
u.last_name,
SUM(a.completed) as completed_sum
FROM form_assignments a
JOIN forms f ON (form_id = f.id)
JOIN users u ON (sender_id = u.id)
JOIN priorities p ON (priority_id = p.id)
WHERE recipient_id = '{$_SESSION['user_id']}'
ORDER BY due_date ASC";
And a while loop like this:
$assignment_count = (mysqli_num_rows($result));
$assignments_row = array();
while ($row = mysqli_fetch_array($result)) {
$sender = $row['first_name'] . ' ' . $row['last_name'];
$form_id = $row['form_id'];
$form_name = $row['name'];
$priority = $row['priority'];
$due_date = date('m/d/Y', strtotime($row['due_date']));
$completed = $row['completed'];
$not_done = $assignment_count - $row['completed_sum'];
}
And it's only returning one row. It seems my SUM(a.completed) as completed_sum is causing the issues because the query worked fine before I added it, but I want to add up all the values in completed to use in my $not_done variable.
Can anyone help clarify what I'm doing wrong?
When you use an aggregate function like SUM, all the results will be aggregated into one row unless you use a GROUP BY clause to segregate them. But it looks to me like you don't need a SUM in the first place. Your loop is subtracting this value from a total, so you just need the value from each row -- when you subtract them all you'll have subtracted the total. So just select a.completed rather than SUM(a.completed).
For $not_done, you need to initialize it before the loop:
$not_done = $assignment_count;
Then during the loop you should do a running subtraction:
$not_done -= $row['completed'];
Try this query :
SELECT
a.sender_id,
a.recipient_id,
a.form_id,
a.due_date,
a.completed,
f.name,
p.priority,
u.first_name,
u.last_name,
b.completed as completed_sum
FROM
form_assignments AS a
LEFT JOIN (
SELECT form_id,SUM(completed) FROM form_assignments GROUP BY form_id
) AS b ON (a.form_id = b.form_id)
LEFT JOIN forms AS f ON (form_id = f.id)
LEFT JOIN users AS u ON (sender_id = u.id)
LEFT JOIN priorities AS p ON (priority_id = p.id)
WHERE
recipient_id = '{$_SESSION['user_id']}'
ORDER BY due_date ASC

Categories