Having trouble with SQL command logic - please help - php

I am using the following statement to fill an Excel spreadsheet with student information, including "actualstudenthours."
The problem is, I want to show all students for which the tblstudentstatus.id = 3, but I also need to show actual student hours for those students. Unfortunately, not all of the students have a corresponding entry in "viewactualstudenthours." This statement completely leaves out those students for which there is no corresponding entry in "viewatualstudenthours."
How do I get all the students to show up where the tblstudentstatus.id = 3?
If there is no entry for them in viewactualstudenthours, it should not omit the student entirely...the student hours fields should just be blank. Your help would be greatly appreciated.
$result=mysqli_query($dbc,"SELECT tblstudent.first, tblstudent.last,
LEFT(viewactualstudenthours.ACTUAL_remain,5),
(SELECT first from tbladdress where tbladdress.id = tblstudent.contact2),
(SELECT last from tbladdress where tbladdress.id = tblstudent.contact2),
tbladdress.address1,tbladdress.city,tbladdress.state,tbladdress.zip1,
tbladdress.phone, tbladdress.cell, tbladdress.email
FROM tblstudent, tbladdress, tblstudentstatus, viewactualstudenthours
WHERE viewactualstudenthours.student_id = tblstudent.id
AND tblstudent.status = tblstudentstatus.id
AND tbladdress.id = tblstudent.contact1
AND tblstudentstatus.id = 3");
(Note: the editor made the SQL semi-legible - but probably broke every rule in the PHP code book.)

Learn to use the explicit join notation introduced in SQL-92 instead of the older comma-separated list of table names in the FROM clause.
You need to use a LEFT OUTER JOIN of the table tblstudent with the view viewactualstudenthours. Ignoring the quotes etc needed to make the code work in PHP, you need:
SELECT S.first, S.last,
H.ACTUAL_remain,
A2.first, A2.last,
A1.address1, A1.city, A1.state, A1.zip1,
A1.phone, A1.cell, A1.email
FROM tblstudent AS S
JOIN tbladdress AS A1 ON S.Contact1 = A1.ID
JOIN tbladdress AS A2 ON S.Contact2 = A2.ID
JOIN tblstudentstatus AS T ON S.Status = T.ID
LEFT JOIN viewactualstudenthours AS H ON S.ID = H.Student_ID
WHERE T.id = 3
Also learn to use table aliases (the AS clauses) - it simplifies and clarifies the SQL. And if the schema is up to you, don't prefix the table names with 'tbl' and the view names with 'view' - it is just so much clutter.
Note that I got rid of the sub-selects in the select-list by joining to the Address table twice, with two separate aliases. I removed the function LEFT(); you can reintroduce it if you need to.

Related

Multi-Table, Multi-WHERE and SELECT MySQL query

So, I am trying to select some data from 4 tables using a query I have attempted to throw together.
SELECT *
FROM cards
LEFT JOIN cards_viewers ON cards.card_id = cards_viewers.card_id
(SELECT *
FROM folders
WHERE folder_id = cards.card_folderID)
(SELECT user_firstName,
user_lastName,
user_avatar
FROM user_data
WHERE user_id = cards_viewers.user_id)
WHERE cards_viewers.user_id = '.$u_id.'
ORDER BY cards.card_lastUpdated DESC
Basically, the query selects data from the four tables depending on the user_id in table user_data. I have attempted to initially fetch all data from the tables cards, and cards_viewers, and have went on to use this data to select values from the other tables (user_data and folders).
The query is wrong, I know that. I have learnt the majority of basic MySQL, but I am still struggling with more complex queries like the one I am trying to write now. What query can I use to select the data I want?
Links to any documentation to parts of queries would prove very useful in helping me learn how to create queries in future, rather than just relying on StackOverflow.
Many thanks.
You don't need "MULTI-WHERE" but multiple joins, you just need to keep doing joins until you get the tables you need.
Here's an example:
SELECT *
FROM cards LEFT JOIN cards_viewers
ON cards.card_id = cards_viewers.card_id
LEFT JOIN folders
ON folders.folder_id = cards.card_folderID
LEFT JOIN user_data
ON user_id = cards_viewers.user_id
WHERE cards_viewers.user_id = '.$u_id.'
ORDER BY cards.card_lastUpdated DESC
To custom the fields you want to get just change * for the name of the field being careful about ambiguous column naming.
For further information check MySql Joins. Hope this helped you :)

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.

MySQL not showing duplicate column names in separate tables using INNER JOIN

I have a database with 22 tables most tables have a few column fields with identical names. When I use INNER JOIN on the tables with the duplicate column names it will ignore them in the last table. Right now I am only joining 3 tables
SELECT * FROM company C
INNER JOIN typeofdealer PI ON C.CompanyID = PI.CompanyID
INNER JOIN typeofservices TS ON PI.CompanyID = TS.CompanyID
So in this example typeofdealer and typeofservices both contain column names Other and OtherText When I get this query back I only see one Other and one OtherText.
I just discovered as I was writing this that if I do the query in "phpmyadmin" that I get it back exactly as intended. I am doing this query using prepared statements in php and outputting the results using:
echo "<PRE>";
print_r($results);
echo "</PRE>";
I believe the problem is that php arrays cannot contain duplicate fields so is there a way to circumvent the issue I am having?
The workaround you can do for this is to use an alias AS to make a distinction between columns with the same names. Something like:
SELECT PI.Other AS Other1, PI.OtherText AS OtherText2, TS.Other AS Other2, TS.OtherText AS OtherText2 FROM company C
INNER JOIN typeofdealer PI ON C.CompanyID = PI.CompanyID
INNER JOIN typeofservices TS ON PI.CompanyID = TS.CompanyID
Actually it will work the same way if you omit the AS keyword say SELECT PI.Other Other1, PI.OtherText OtherText2
The problem is, as you rightfully suggested, that PHP won't allow multiple entries into an array with the same key name.
The simplest way around this, is to alias the fields in the column selection section of the query, like so:
SELECT *, typeofservices.Other as ServicesOther, typeofservices.OtherText as ServicesOtherText FROM company C
INNER JOIN typeofdealer PI ON C.CompanyID = PI.CompanyID
INNER JOIN typeofservices TS ON PI.CompanyID = TS.CompanyID
It's not pretty but it's simple.

MySQL Join Explanation [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
SQL Join Differences
$PERSON = $DATABASE_LINK->query("SELECT * FROM `users`,`profiles` WHERE users.first_name = 'shane' && users.last_name = 'larson' && users.setup = '1' && profiles.zipcode = '53511' ORDER BY `full_name` ASC");
$PERSON = $PERSON->fetch_object();
var_dump($PERSON);
I want a query that scans for a user record based off name, and checks the zip code from the profile table. Above is a example. It works, but idk how joins work exactly. Any explanation on how joins match 2 rows would be awesome :)
the result set that you are receiving is a cross product of all rows in the user table that match the users criteria and all rows in the profiles table that match the profiles criteria.
It seems likely that this is not what you want.
consider adding something like users.blammy = profiles.blammy to join the two tables.
SELECT Cities.Name, Countries.Name, Countries.id
FROM Cities INNER JOIN Countries
ON Cities.CountryId = Countries.id
WHERE Cities.Name LIKE = 'town' LIMIT 10
Looking at that example:
The first row selects three columns from two different tables (Cities and Countries).
The second row specifies the two tables to join.
The third row specifies what item to match the two tables on.
The result from that query is a list
of Cities.Name that match the LIKE
clause and their corresponding
Countries.Name (which it finds by
matching Cities.CountryId with
Countries.id).
Read more here: http://www.wellho.net/mouth/158_MySQL-LEFT-JOIN-and-RIGHT-JOIN-INNER-JOIN-and-OUTER-JOIN.html
So using SQL Statements with "WHERE table1.id_x = table2.id_y" do work, but as far as i know they are slower than Joins (primarly with huge datasets).
So there inner and outer Joins, the outer Joins are divided into left- and right-joins.
A little Explanation for a left-Join:
SELECT Class.Id, Class.Name, Professor.Id, Professor.Name
FROM FROM Professor INNER JOIN Class
ON Professor.Id = Class.ProfessorId;
This Statement Selects all Professors, and does not care if a Professor don't teaches a Class. But if there is a class without a Professor, this class is not selected. It's called left Join because 'NULL' References in the left Table are ignored. The explanation for the right-Join should be trivial ;)
SELECT Class.Id, Class.Name, Professor.Id, Professor.Name
FROM FROM Professor LEFT OUTER JOIN Class
ON Professor.Id = Class.ProfessorId;
The Inner Join don't shows Professors without Classes and it don't shows Classes without Professors.
Please remember: Not all DBMS got the Keywords 'INNER' and 'OUTER' ;)

Joining multiple (4) tables in MYSQL

I have four tables I want to join and get data from. The tables look something like...
Employees (EmployeeID, GroupID[fk], EmployeeName, PhoneNum)
Positions (PositionID, PositionName)
EmployeePositions (EployeePositionID, EmployeeID[fk], PositionID[fk])
EmployeeGroup (GroupID, GroupName)
[fk] = foreign key
I want to create a query that will return all the information about an employee(given by EmployeeID). I want a query that will return the given employees Name, position(s), and group in one row.
I think it needs to involve joins, but I am not sure how to format the queries. MYSQL's manual is technical beyond my comprehension. I would be very grateful for any help.
It seems you have trouble with SQL, in general, rather than with mySQL in particular. The documentation of mySQL provides details about the various SQL expressions, but generally assume some familiarity with SQL. To get a quick start on SQL you may consider this W3schools.com primer.
The query you need is the following.
SELECT EmployeeName, PositionName, GroupName
FROM Employees E
LEFT JOIN EmployeePositions EP ON EP.EmployeeID = E.EmployeeID
LEFT JOIN Positions P ON P.PositionID = EP.PositionId
LEFT JOIN EmployeeGroup EG ON EG.GroupId = E.GroupId
WHERE E.EmployeeId = some_value
A few things to note:
The 'LEFT' in 'LEFT JOIN' will result in producing NULL in lieu of PositionName or GroupName when the corresponding tables do not have a value for the given FK. (Should only happen if the data is broken, say if for example some employees have GroupId 123 but somehow this groupid was deleted from the EmployeeGroup table.
The query returns one line per employee (1). You could use an alternative search criteria, for example WHERE EmployeeName = 'SMITH', and get a listing of all employees with that name. Indeed without a WHERE clause, you'd get a list of all employees found in Employees table.
(1) that is assuming that each employee can only have one position. If somehow some employees have more than one position (i.e. multiple rows in EmployeePositions for a given EmployeeID), you'd get several rows per employee, the Name and Group being repeated and a distinct PostionName.
Edit:
If a given employee can have multiple positions, you can use the query suggested by Tor Valamo, which uses a GROUP BY construct, with GROUP_CONCAT() to pivot all the possible positions in one single field value in the returned row.
SELECT e.EmployeeID, e.EmployeeName, e.PhoneNum,
g.GroupName, GROUP_CONCAT(p.PositionName) AS Positions
FROM Employees e
LEFT JOIN EmployeeGroup g ON g.GroupID = e.GroupID
LEFT JOIN EmployeePositions ep ON ep.EmployeeID = e.EmployeeID
LEFT JOIN Positions p ON p.PositionID = ep.PositionID
WHERE e.EmployeeID = 1
GROUP BY e.EmployeeID
Returns positions in a comma separated string on one row.

Categories