Creating a completion table (PHP and MYSQL) - php

My database has a challenges table where there are these columns: Challenge_Name, Challenge_Description. I have a 2nd table called completed_challenges_junction and it has these columns: Member_Name, Challenge_Name.
I need a way to display all of the challenge names from the challenges table along with the member names within the completed_challenges_junction. If there is no match then I would like it to display NULL.
I think I'm pretty close to having my SQL code working, here is what I have now.
SELECT challenges.Challenge_Name, challenges.Challenge_Description, completed_challenges_junction.Member_Names
FROM challenges
LEFT JOIN completed_challenges_junction ON challenges.Challenge_Name=completed_challenges_junction.Challenge_Name
This works but also bring duplicate entries of another member. If i use WHERE Member_Name='testmember' it only brings the entries of the member when I need it to still display all Challenge_Names.

SELECT
A.Challenge_Name,A.Challenge_Description,
GROUP_CONCAT(IFNULL(B.Member_Names,'')) Member_Names
FROM
challenges A
LEFT JOIN completed_challenges_junction B ON
A.Challenge_Name=B.Challenge_Name AND
A.Challenge_Description=B.Challenge_Description
GROUP BY
A.Challenge_Name,A.Challenge_Description
;
or
SELECT
A.Challenge_Name,A.Challenge_Description,
GROUP_CONCAT(IFNULL(B.Member_Names,'')) Member_Names
FROM
challenges A
LEFT JOIN completed_challenges_junction B
USING (Challenge_Name,Challenge_Description)
GROUP BY
A.Challenge_Name,A.Challenge_Description
;

You could add the WHERE clause into the ON condition like this
SELECT challenges.Challenge_Name, challenges.Challenge_Description, completed_challenges_junction.Member_Names
FROM challenges
LEFT JOIN completed_challenges_junction ON (
challenges.Challenge_Name=completed_challenges_junction.Challenge_Name
AND Member_Name='testmember'
)
This way only testmember entries will come up from completed_challanges_junction, but all challenges will be displayed.

I'm not sure what exactly you want, but maybe you are looking for 'group by' clause and group_concat function:
SELECT challenges.Challenge_Name, challenges.Challenge_Description,
GROUP_CONCAT(completed_challenges_junction.Member_Names SEPARATOR ', ')
FROM challenges
LEFT JOIN completed_challenges_junction
ON challenges.Challenge_Name=completed_challenges_junction.Challenge_Name
GROUP BY challenges.Challenge_Name
This query will return result where each Challenge_Name occurs only once.

Related

join of two sql tables

I have two tables and I want to join them to get the desired output.
Say the 1st table (seat1) is
and the 2nd table (collegestudents) is
The desired output is
I have tried the below code. But it fails to give the desired result.
$rde2=mysqli_query($con, "select * from seat1 s
left JOIN collegestudents c ON c.Roll = s.Roll
");
Any help please.
You want a left join. Your query looks fine, but you would need not to use select *, and instead explictly list the columns that you want to select, using table prefixes. Otherwise, since you have a Roll column in both tables, a name clashes will happen, that your application apparently does not handle well.
select
s.Roll,
c.Name,
s.Subject
from seat1 s
left join collegestudents c on c.Roll = s.Roll

Combining two MySQL tables yet want one column to equal another

I am trying to join two tables together in a view. My first table combines two tables but now I am trying to join that table to a second table. I am trying to use a join to make sure the second table which contains roles which are performed by the user, matches up with the first table but if there are no records in the second table, I still want all the records from table 1. I know my explanation is a little confused, so my code is as follows:
CREATE VIEW `data` AS SELECT
`information`.`username`, `information`.`department`,
`information`.`company`, `information`.`title`,
`information`.`internal_number` AS `user_internal_phone`,
`information`.`external_number`AS `user_external_phone`,
`information`.`mail`, `information`.`cn` AS `name`, `information`.`hours`,
`information`.`languages`, `information`.`functions`,
`information`.`service` AS `contact_point_name_one`,
`information`.`subservice` AS `contact_point_name_two`,
`information`.`internal_phone` AS `contact_internal_phone`,
`information`.`external_phone` AS `contact_external_phone`,
`information`.`keywords`, `information`.`description`,
`information`.`provided_by`, `information`.`id`,
GROUP_CONCAT(`staff_roles`.`role` SEPARATOR ', ') AS `roles`,
`staff_roles`.`user`
FROM `information`
CROSS JOIN `staff_roles` ON `information`.`username` = `staff_roles`.`user`;
I get an error when I do an outer join and a cross join and an inner join both return rows where there is a row in both tables yet I want it to display the rows where there is nothing in the second table as well. The purpose of using a join is so that, where there is a match, the row from table 2 should match the row on table 1
Use LEFT JOIN. The LEFT JOIN keyword returns all rows from the left table (table1), with the matching rows in the right table (table2). The result is NULL in the right side when there is no match.
Just replace your CROSS JOIN with LEFT JOIN
Simply use LEFT JOIN instead of CROSS JOIN:
CREATE VIEW `data` AS SELECT
...
FROM `information`
LEFT JOIN `staff_roles` ON `information`.`username` = `staff_roles`.`user`;
Take a look at http://www.w3schools.com/sql/sql_join_left.asp for further details about why LEFT JOIN.

Excess colomns in the query result

I'm trying to write a simple interface for a list of companies using MySQL and PHP. So, I want to fetch some information from my database.
Here are my tables:
companies_data - only for system information.
corporate_data - here I want to keep information about big companies.
individual_data - and here I want to keep information about little companies.
So, here is the tables
And here is the query that I've written:
SELECT
a.id,
a.user_id,
a.added,
a.`status`,
a.company_id,
a.company_type,
a.deposit,
a.individual_operations_cache,
a.corporate_operations_cache,
a.physical_operations_cache,
b.full_name,
b.tax_number,
b.address,
b.statement_date,
b.psrn,
c.full_name,
c.tax_number,
c.address,
c.statement_date,
c.psrn
FROM
companies_data a
LEFT OUTER JOIN corporate_data b
ON (a.company_id = b.id) AND a.company_type = 0
LEFT OUTER JOIN individual_data c
ON (a.company_id = c.id) AND a.company_type = 1
WHERE
a.user_id = 3
This is just the code for a test, I'll expand it soon.
As you see, I've got result with extra fields like %field_name%1, %another_field_name%1 and so on. Of course it is not the mysql error - what I've asked that I've got - but I want to remove this fields? It's possible or I must convert this output on the application side?
thos %field_name%1, %another_field_name%1 , are visible since you are selecting them in your query:
b.full_name,
b.tax_number,
b.address,
b.statement_date,
b.psrn,
c.full_name,
c.tax_number,
c.address,
c.statement_date,
c.psrn
When you use fields with the same name in distinct tables, then the result column name come with this identifier field1, field2, fieldn... in order to distinguish from which table does the field come from.
If you want to avoid this names, you can use aliases as follows:
[...]
b.full_name as corporate_full_name,
[...]
Probably, if every common fields are coincident, you won´t need to show them all, so just remove them from the select.
Hope being usefull for you.
Br.

Join mysql with multiple queries

I have three different SQL tables I need to join:
table "internet" with columns id|type|status
table "type_list" with columns id|type_name
table "status_list" with columns id|status_name
I want to output text from the two other tables (type_list, status_list) but not values as numbers which currently I have in table "internet".
I also don't want to make lazy programming - PHP array to make ID's equal to something like
$type_list = array("1"=>"VDSL2","2"=>"ADSL");
$status_list = array("1"=>"Pending","2"=>"Active");
because the text is already in the tables, i just dont know how to join them and output the text as query combined together in one query.
Use JOIN
SELECT i.id, type_name, status_name
FROM internet i
LEFT OUTER JOIN type_list t ON t.id = i.type
LEFT OUTER JOIN status_list s ON s.id= i.status
Read the MySQL doc for more informations.
Just write the select with the fields you want.
select internet.id,type_name,status_name from internet
inner join type_list
on type_list.id=internet.id
inner join status_list
on status_list.id=internet.id
For this you need a LEFT JOIN, like so:
SELECT i.id, t.type_name, s.status_name
FROM internet AS i
LEFT JOIN type_list AS t ON t.id = i.id
LEFT JOIN status_list AS s ON s.id= i.id
From your question, it is unclear what field you would like to join the queries on. In the above example, the queries are joined on the id field.
Please also note that the AS is not actually necessary, I have just put it in there to make it clear what is going on

Tricky MySQL query involving NOT IN

I have two tables that I am joining together in order to get results.
One table contains a list of assessments with a unique ID (assessments), whilst the other table (staff_to_assessments) contains a list of assessments that are assigned to staff members. An example record for this table would contain the Staff member unique ID, and the assignment unique ID. This shows that a user has been linked to an assignment.
I have written a function which only grabs assessments from the assessment table where they have not been assigned to a staff member in staff_to_assessment table. This is to populate a drop-down box on the front end where these remaining assessments can be assigned to a staff member if required, therefore I don;t want to show any that are already assigned.
MySQL query is as follows:
SELECT * FROM assessments a
LEFT JOIN staff_to_assessment s2a ON a.assessment_id = s2a.assessment_id
WHERE a.assessment_id NOT IN
(SELECT assessment_id FROM staff_to_assessment WHERE staff_id = '" . (int)$options['staffId'] . "')";
This doesn't seem to generate the response I need. Can anybody see where I have gone wrong?
Thanks!!
I think your query is working too hard. You just need to find rows where there is no match to the left outer join:
SELECT a.*
FROM assessments a LEFT JOIN
staff_to_assessment s2a
ON a.assessment_id = s2a.assessment_id
WHERE s2a.assessment_id is null;
You don't need to use both a left join and a not in clause.
Queries like NOT IN [subquery] can (and should) always be rewritten as a LEFT JOIN.
SELECT a.*
FROM assessments a
LEFT JOIN staff_to_assessment s2a USING (assessment_id) -- equivalent to "ON a.assessment_id = s2a.assessment_id", as both columns have the same name
WHERE staff_id IS NULL
This is equivalent to:
SELECT a.*
FROM assessments a
WHERE a.assessment_id NOT IN (SELECT assessment_id FROM staff_to_assessment)
Both are usually optimised away to the same execution plan, but the former is preferable as it tends to produce quicker queries.

Categories