How do I stop duplicate rows on table join in SQL? - php

Trying to join this table, so that i can change the code if the tutor ID matches the session tutor ID. But it shows multiple results in the calendar that its generating.
Below is the current PHP code, although the entries are being duplicated due to having multiple tutor ID's within the table. i'm not sure how to change this.
<?php
$sqlAssignments = "SELECT * FROM tbl_assignments LEFT JOIN tbl_tutorModules ON tbl_assignments.module_code = tbl_tutorModules.module_code"; //
$qryAssignments = mysqli_query($con, $sqlAssignments); // running the query
while($rowAssignment = mysqli_fetch_assoc($qryAssignments)){
if ($_SESSION["ID"] == $rowAssignment['tutor_id']) {
echo "{ title: '" . $rowAssignment['assignment_name'] . "', start: '" . $rowAssignment['hand_in_date'] . "', end: '" . $rowAssignment['hand_in_date'] . "', url: 'view/assignments.php?id=" . $rowAssignment['assignment_id'] . "', color: '#f1f1f1'},";
} else {
echo "{ title: '" . $rowAssignment['assignment_name'] . "', start: '" . $rowAssignment['hand_in_date'] . "', end: '" . $rowAssignment['hand_in_date'] . "', url: 'view/assignments.php?id=" . $rowAssignment['assignment_id'] . "'},";
}
}
?>
The actual results at the moment is that when the tutorModules has multiple tutors, the output duplicates calendar results.
Thanks
Edit: Tables look like this with some example data
tbl_tutorModules
con_id module_code tutor_id
2 ISYS30025 1
3 ISYS30025 2
tbl_assignments
assignment_id
module_code
assignment_name
assignment_weight
set_date
hand_in_date
hand_in_method
assignment_type
This is the current output
The expected output is for these not to be duplicated.

You want to know whether a certain tutor is involved in an assignment. So pass the tutor ID to the DBMS in order to let it find out in a query.
SELECT
assignment_id, assignment_name, hand_in_date,
case when module_code in (SELECT module_code FROM tbl_tutorModules WHERE tutor_id = ?)
then 'yes' else 'no'
end as tutor_involved
FROM tbl_assignments
ORDER BY assignment_id;
As you can see, I don't join the tables, because I'm not interested in the joined result. I merely want to look up a record in tbl_tutorModules. We use IN or EXISTS in SQL to look up records in another table.
See here how to pass parameters to the DBMS in mysqli: http://php.net/manual/en/mysqli.prepare.php

Related

How to fix slow query performance using NOT EXISTS MySQL? CodeIgniter

I am trying to optimize / speed up the performance the loading of my data, is there a way to fix this?
I have 3 tables involved:
tbl_tt_college_studentpersonalinfo - This table displays the name of students, it is join in my query
tbl_tt_college_preenrollment - This table displays the pending status of pre-enrolled students
tbl_tt_college_enlistment - This table will check the existing record the student has.
Here is my Query: - The problem that I am having is the load of data is slow, it may take 30-50 seconds. Is there a way to improve this or make it like a join query?
public function get_enlists()
{
$this->db->join('tbl_tt_college_studentpersonalinfo','tbl_tt_college_preenrollment.studentID = tbl_tt_college_studentpersonalinfo.studentID');
$this->db->where('tbl_tt_college_preenrollment.departmentID', $this->input->post('course'));
$this->db->where('tbl_tt_college_preenrollment.yearLevel', $this->input->post('yearLevel'));
$this->db->where("NOT EXISTS (SELECT tbl_tt_college_enlistment.studentKeyID FROM tbl_tt_college_enlistment WHERE tbl_tt_college_enlistment.studentKeyID = tbl_tt_college_preenrollment.studentKeyID AND schoolYear = '" . $this->session->userdata('currentAcademicYear') . '-' . ($this->session->userdata('currentAcademicYear') + 1) . "' AND semester = '" . $this->session->userdata('currentSemester') . "')");
$query = $this->db->get('tbl_tt_college_preenrollment');
return $query->result_array();
}
Here is the raw query for the reference:
NOT EXISTS (
SELECT studentKeyID FROM tbl_tt_college_enlistment
WHERE tbl_tt_college_studentpersonalinfo.studentKeyID = tbl_tt_college_enlistment.studentKeyID
AND schoolYear = '" . $this->session->userdata('currentAcademicYear') . '-' . ($this->session->userdata('currentAcademicYear') + 1) . "'
AND semester = '" . $this->session->userdata('currentSemester') . "'
)
See if this composite index on tbl_tt_college_enlistment helps:
INDEX(schoolYear, semester, studentKeyID)
If not adequate, please provide SHOW CREATE TABLE and EXPLAIN SELECT ...

How do I write a SELECT IF statement with 2 conditionals?

so I got this PHP code here:
SELECT status , IF(type = '" . mysqli_real_escape_string($con,$type) . "' , type, '') AS status FROM novacorp.status WHERE type = '" . mysqli_real_escape_string($con,$type) . "' LIMIT 1;
I also want to add another conditional to this so it'll only select status if the info column is also equal to something which I pass using escape string just like shown above.
Same for this statement:
UPDATE `novacorp`.`status` SET `status`=". $status ." WHERE `type`='" . mysqli_real_escape_string($con,$type) . "';
IF(type=whatever AND info=other, valueiftrue, valueiffalse)
is probably what you want

cannot retrieve data from 2 tables getting no result

I have 2 tables:
competition_winners where I am storing people who won competition and table competition where I am storing info about actual competition.
So I am retrieving winners and competition's end date. But the query responsible for date doesn't return anything. I am using Opencart so performing query in model. Here is its code.
public function getWinnersByDate($date) {
$qr = "SELECT competition_id FROM " . DB_PREFIX . "competition_winners";
//$fcid = $qr->row['competition_id'];
$query = "SELECT cometition_id,end_date FROM " . DB_PREFIX . "competition WHERE competition_id = '" .$qr->row['competition_id'] . "'";
return $query->row;
Query works fine in PhpMyadmin. What am I missing or doing wrong?
Instead of running this in two queries You should be using JOIN (search about SQL JOIN on google).
public function getWinnersByDate($date) {
$qr = $this->db->query("
SELECT cw.competition_id, c.end_date
FROM " . DB_PREFIX . "competition_winners cw
LEFT JOIN " . DB_PREFIX . "competition c ON c.competition_id = cw.competition_id
");
return $query->rows;
}
I do not know Your DB structure, but the query above has no sense in it's current state - I believe You want to add some WHERE clause using the provided $date argument and that You want to select more information from competition_winners table, so please, either do it Yourself or provide us with more details on Your problem.

MySQL/PHP Eliminating duplicate, non-identical, returns from a MySQL self-join

I have a small database, holding the details of just under 400 ponies. I wish to query that table and return a table showing the pertinant details of each pony, and it's owner's and breeder's names. The data is held primarily like so:
profiles - a table holding all info assigned to each individual pony, including it's sire's and dam's reg numbers, and it's owner's and breeder's DB assigned id's.
contacts - a table for the people's info. Joined as 'owner' and again as 'breeder' in the query below.
prm_* - multiple parameter tables, holding broad details such as colour, breed, etc.
Where I am running into trouble is when trying my first self join: querying the profiles table three times in order to retrieve the names of the sire and dam for each profile, as well as the pony's own name to begin with. When I run the query, it returns duplicate rows for many (not all) profiles. Using DISTINCT eliminated most of these, but the issue remains with the non-identical results, particularly for those ponies where no sire or dam is on record.
I have googled the problem, and it does appear here and there, but I cant quite grasp what happening in the solutions given. I'm not even certain why the problem occurs at all. Can someone please step me through the issue and the solving of it? I'd be most grateful.
My query as it stands (returns 408 results, from only 387 ponies!):
include 'conn.php';
?>
<table class="admin-display">
<thead><tr><th>No:</th><th>Name:</th><th>Sire:</th><th>Dam:</th><th>Age:</th><th>Colour:</th><th>Gender:</th><th>Owner:</th><th>Breeder:</th></tr></thead>
<?php
$i=1;
$sql = mysql_query("SELECT DISTINCT p.ProfileID, p.ProfileOwnerID, p.ProfileBreederID, p.ProfilePrefix, p.ProfileSireReg, p.ProfileDamReg,
p.ProfileGenderID, p.ProfileAdultColourID, p.ProfileColourModifierID, p.ProfileYearOfBirth,
p.ProfileYearOfDeath, p.ProfileLocalRegNumber, p.ProfileName,
sire.ProfileName AS sireName, sire.ProfilePrefix AS sirePrefix,
dam.ProfileName AS damName, dam.ProfilePrefix AS damPrefix,
owner.ContactFirstName AS owner_fname, owner.ContactLastName AS owner_lname,
breeder.ContactFirstName AS breeder_fname, breeder.ContactLastName AS breeder_lname,
BreedGender, BreedColour, BreedColourModifier
FROM profiles AS p
LEFT JOIN profiles AS sire
ON p.ProfileSireReg = sire.ProfileLocalRegNumber
LEFT JOIN profiles AS dam
ON p.ProfileDamReg = dam.ProfileLocalRegNumber
LEFT JOIN contacts AS owner
ON p.ProfileOwnerID = owner.ContactID
LEFT JOIN contacts AS breeder
ON p.ProfileBreederID = breeder.ContactID
LEFT JOIN prm_breedgender
ON p.ProfileGenderID = prm_breedgender.BreedGenderID
LEFT JOIN prm_breedcolour
ON p.ProfileAdultColourID = prm_breedcolour.BreedColourID
LEFT JOIN prm_breedcolourmodifier
ON p.ProfileColourModifierID = prm_breedcolourmodifier.BreedColourModifierID
WHERE p.ProfileName != 'Unknown'
ORDER BY p.ProfileID ASC");
while($row = mysql_fetch_array($sql)) {
$id = $row['ProfileID'];
$name = $row['ProfilePrefix'] . ' ' . $row['ProfileName'];
if ($row['ProfileYearOfDeath'] > 0000) { $age = ($row['ProfileYearOfDeath'] - $row['ProfileYearOfBirth']); }
elseif ($row['ProfileYearOfDeath'] <= 0000) { $age = (date('Y') - $row['ProfileYearOfBirth']); }
$reg = $row['ProfileLocalRegNumber'];
$sire = $row['sirePrefix'] . ' ' . $row['sireName'];
$dam = $row['damPrefix'] . ' ' . $row['damName'];
$colour = $row['BreedColour'];
$gender = $row['BreedGender'];
$owner = $row['owner_fname'] . ' ' . $row['owner_lname'];
$breeder = $row['breeder_fname'] . ' ' . $row['breeder_lname'];
echo '<tr><td>' . $i++ . '</td><td>' . $name . '</td><td>' . $sire . '</td>';
echo '<td>' . $dam . '</td><td>' . $age . '</td><td>' . $colour . '</td><td>' . $gender. '</td>';
echo '<td>' . $owner . '</td><td>' . $breeder. '</td></tr>';
}
echo '</table>';
mysql_close($con);
Use GROUP BY over DISTINCT:
http://msmvps.com/blogs/robfarley/archive/2007/03/24/group-by-v-distinct-group-by-wins.aspx
The problem is going to be in the data - one of the tables that you're joining against has multiple rows on associated to the join key.
I recommend executing the query in stages. Start with the base query (taking out the field list):
SELECT count(*)
FROM profiles AS p
WHERE p.ProfileName != 'Unknown'
And then add the join tables in one at a time until you see the count increase...
SELECT count(*)
FROM profiles AS p
LEFT JOIN profiles AS sire
ON p.ProfileSireReg = sire.ProfileLocalRegNumber
WHERE p.ProfileName != 'Unknown'
You should then be able to see where the duplicate is. If you want to easily see which record is duplicated, you can run this query:
SELECT p.Profile_id, count(*) cnt
FROM profiles AS p
LEFT JOIN profiles AS sire
ON p.ProfileSireReg = sire.ProfileLocalRegNumber
-- (all other joins)
WHERE p.ProfileName != 'Unknown'
GROUP BY p.Profile_id
HAVING count(*) > 1
Then you can look at the details of the duplicated records.

Order by Total For Sum function used

<?
$tablae = mysql_query("SELECT * FROM order_history where (type!='rent_referral' AND type!='rental_balance') AND date>'" . strtotime($time1) . "' AND date<'" . strtotime($time2) . "' GROUP BY user_id");
while ($order = mysql_fetch_array($tablae)) {
?>
<tr>
<?
$tablaes = mysql_query("SELECT * FROM members where id='$order[user_id]'");
$user = mysql_fetch_array($tablaes);
$idsd=$user['id'];
$rPaid=mysql_query("SELECT SUM(`price`) AS total FROM order_history WHERE (type!='rent_referral' AND type!='rental_balance') AND date>'" . strtotime($time1) . "' AND date<'" . strtotime($time2) . "'");
$hdPaid = mysql_fetch_array($rPaid);
$sPaid=mysql_query("SELECT SUM(`price`) AS total FROM order_history WHERE user_id='$idsd' AND (type!='rent_referral' AND type!='rental_balance') AND date>'" . strtotime($time1) . "' AND date<'" . strtotime($time2) . "'");
while ($hPaid = mysql_fetch_array($sPaid)) {
?>
<td><?=$user['username']?></td>
<td><?=$hPaid['total']?></td>
<?
}
?>
</tr>
<? } ?>
This gets me this result http://dl.dropbox.com/u/14384295/test.jpeg
I want to order the price totals by DESC.
I would need
$sPaid=mysql_query("SELECT SUM(`price`) AS total FROM order_history WHERE user_id='$idsd' AND (type!='rent_referral' AND type!='rental_balance') AND date>'" . strtotime($time1) . "' AND date<'" . strtotime($time2) . "'");
the total on that to be ordered by DESC.
Be really carefull with GROUP BY instructions in your SQL query. All columns which are in the result and which are not aggregate expressions (expressions would be the count, SUM, max, etc working on the group and not on the rows) should be in your group by expression;
Here you use a select *, you should try to list the real columns instead, and get this list in your group by, or use only SELECT user_id.
Most database would prevent you of running such not-very-well-formted group by query, but MySQl is not bailing you, tthat does not mean he won't gives you completly wrong results if you do not rexpect this rule (all columns which are not aggregates must be in the group by).
Then you should be able to order by an agregate expression by reusing this expression and not his alias in the order clause.
You could either use client side sorting with javascript, there are some nice jQuery addons that can do that.
Or you have to totaly rewrite your code to have a single sql using joins and group by.
But I cannot realy follow the logic with $rPaid, $hPaid and $sPaid so I cannot help you there.

Categories