I am downloading from my database people working for different companies and I want to create associative array with values "source" and "target" which represent company IDs that the employee works for. There are at least 2 rows for the same person from my query so I know that each person from my query works at least for 2 companies.
Example if 'Aberdeen asset management plc' works for 'New India Investment Trust PLC' (Company ID 300) and for 'Aberdeen New Dawn Investment Trust PLC' (Company ID 4), I would want to have a row in my array like:
"source"=>300,"target"=>4,"officers"=>'Aberdeen asset management plc'
Source & Target are interchangable the order does not matter. Each employee could have multiple rows added if he works for more than 2 companies. The only issue occurs when employee works for odd number of companies but then target/source could be set to the previous source/target that this person works for.
Data example:
while($row = mysqli_fetch_array($dataDB)){
array_push($data, array("Company_ID"=>intval($row['Company_ID']),"Company_Name"=>$row['Company_Name'],"Company_Index"=>$row['Company_Index'], "Officer_Name"=>$row['Officer_Name'], "Officer_Role"=>$row['Officer_Role']));
}
$edges = array();
foreach($data as $d){
array_push($edges, array("source"=>$d['Company_ID']),"target"=>'',"officers"=>array($d['Officer_Name'])));
}
SQL Query is quite long since it is taking into consideration that employees are still working not resigned and taking only workers that work for more than 1 company:
SELECT
CD.Company_ID,
CD.Company_Name,
CD.Company_Index,
OD.Officer_Name,
CO.Officer_Role
FROM
Company_Details CD
INNER JOIN Company_Officer CO
ON CD.Company_ID = CO.Company_ID
INNER JOIN Officer_Details OD
ON CO.Officer_ID = OD.Officer_ID
WHERE CD.Company_Index<>'' AND
CO.Resigned_On='' AND
CO.Officer_ID IN
( SELECT CO2.officer_id
FROM Company_Officer CO2
INNER JOIN Company_Details CD2
ON CO2.Company_ID = CD2.Company_ID
WHERE CO2.Resigned_On='' AND CD2.Company_Index<>''
GROUP BY CO2.officer_id
HAVING Count( DISTINCT CO2.company_id ) > 1
)
ORDER BY `OD`.`Officer_Name` ASC;
Related
I stumbled upon a query that I have never done until now.
Before asking the question I looked for if another user had had the same need as me but nothing.
My goal is very simple:
having two tables:
collaboratori (collaborators)
invite (invitations)
I have to count how many invitations the collaborators have made.
table structure of collaboratori:
ID_Collaboratori | cod_manager
37 4675
150 6675
3 6575
table structure of inviti:
invite_id | invite_code_manager
37 6675
39 6575
40 4675
41 6675
if I execute the join obviously I access the two tables in this way:
$q_stats_prod_manager = $connessione->prepare("
SELECT * FROM invite
LEFT JOIN collaboratori
ON collaboratori.cod_manager = invite.invite_code_manager ");
$q_stats_prod_manager->execute();
$r_stats_prod_manager = $q_stats_prod_manager->get_result();
my need lies in showing in a table:
show me for each manager who has his cod_manager inside the inviti table, the number of times he sent them.
Name Surname Manager 1 | Number of invite: 200
Name Surname Manager 2 | Number of invite: 50
Name Surname Manager 3 | Number of invite: 10
not limiting myself to just one counter but also being able to access other table values like any join
I take the liberty of putting the answer that was partially written by another user, adding a detail and explanation for future users. The resolution query for this case is the same:
$q_stats_prod_manager = $connessione->prepare("
SELECT count(invite.invite_id)
/*name of what you want to call the result you will see in the while*/
AS result_count, /*you can call this value whatever you want*/
/*Start | Values of the tables you are interested in selecting*/
collaboratori.nome,
collaboratori.data_registrazione,
invite.invite_code_manager
/*End | Values of the tables you are interested in selecting*/
FROM collaboratori
LEFT JOIN invite
ON invite.invite_code_manager = collaboratori.cod_manager group by invite.invite_code_manager
");
$q_stats_prod_manager->execute();
$r_stats_prod_manager = $q_stats_prod_manager->get_result();
$count_invite_manager=mysqli_fetch_array($r_stats_prod_manager);
$number_of_invite_manager = $count_invite_manager[0];
Select the id of the table you want to count
Give a name you wish you want to name the counted result
Select the values of the tables on which you will perform the join you want to view
Join the tables
Show the result with while
Code while:
<?php while($rowstatspm = mysqli_fetch_assoc($r_stats_prod_manager)){ ?>
<!-- this is the fancy name you associated with your query when you wrote: AS nameofwhatyouwant -->
<?php echo $rowstatspm['result_count'] ;?>
<?php } ?>
You seem to want aggregation. I assume you want all rows for collaboratori, so that should be the first table for the LEFT JOIN:
SELECT c.cod_manager, COUNT(i.invite_code_manager)
FROM collaboratori c LEFT JOIN
invite i
ON c.cod_manager = i.invite_code_manager
GROUP BY c.cod_manager;
Your question doesn't describe where the name comes from. But those fields should be in both the SELECT and GROUP BY.
SELECT count(invite.invite_id),collaboratori.name FROM collaboratori
LEFT JOIN invite
ON invite.invite_code_manager = collaboratori.cod_manager group by invite.invite_code_manager
► Context : I work in a museum (for real), people come everyday, they buy tickets for themselves (humans) and sometimes they also buy tickets for drinks and foods (objects). There are events, tickets have the same names per event but the prices are different.
► The problem : I have to create a report with 2 results : total sales (visitors + food + drinks) and how many people came (visitors only) for a specific event. Next is an image of the 3 tables in the database, how they relate and some sample data :
Table TICKETS relates to SALES_MAIN through EVENT_ID column.
Table SALES_MAIN relates to SALES_DETAIL through ID→MAIN_ID columns.
Table SALES_DETAIL have a column TICKET_NAME but it's not unique in table TICKETS.
► The question : How to get both results, total sales and human count, for event 555 in one "select" ? I tried next 2 "select" but when I combine them with another INNER JOIN I get cartesian results :
Get detail sales for event 555 :
SELECT sales_detail.* FROM sales_main
INNER JOIN sales_detail ON sales_detail.main_id = sales_main.id
WHERE sales_main.event_id = '555'
Get tickets for event 555 :
SELECT * FROM tickets WHERE tickets.event_id = '555'
Use:
SELECT
SUM(CASE WHEN sd.ticket_name IN ('adult', 'child') THEN sd.quantity
ELSE 0 END) AS total_visitors,
SUM(sd.quantity * t.price) AS total_sales
FROM sales_main sm
JOIN sales_detail sd
ON sd.main_id = sm.id
JOIN ticket t
ON t.event_id = sm.event_id
AND t.ticket_name = sd.ticket_name
WHERE sm.event_id = '555';
Conditional aggregation could also be based on type:
SUM(CASE WHEN t.ticket_type ='human' THEN sd.quantity ELSE 0 END)
Scenario:
The school where I work at has already a system that handles resource reservation (racks with tv's, projectors, etc), however I was asked to make a quick-fix for today since the system has a problem, there's no way to make the resource only appear for a specific segment:
1-6th grade is a segment,
7-11th grade is a segment.
The system is made out of PHP and MySQL.
Problem:
Without creating a new table, I have to find a way to show a specific resource only to 1-3rd grade and another one only to 4-6th grade.
Here are the tables:
I added into the grade table a new column called UNIQUERESOURCESwhere I put a value of 1 to sections between first and third grade and a value of 2 to sections between fourth and sixth grade.
How can I show to grades from 1-3 grade ONLY those specific resources and from 4-6 grade ONLY the other specific resources?
Here is the current query:
SELECT DISTINCT r.RESOURCEID, r.RESOURCENAME, rl.RESOURCELOCATIONNAME FROM resource r
inner join resource_location rl
on r.RESOURCELOCATIONID = rl.RESOURCELOCATIONID
inner join grade g
on g.RESOURCELOCATIONID = r.RESOURCELOCATIONID
inner join users_intermediate ui
on g.GRADEID = ui.GRADEID
WHERE ui.USERID = '%s'
How can I fix this query to include the resources as follows:
Include RESOURCELOCATIONID = 5 where UNIQUERESOURCES = 1 if the user is in between GRADEID 1-12
Include RESOURCELOCATIONID = 6 where UNIQUERESOURCES = 2 if the user is in between GRADEID 13-24.
This is the part I can't figure out. Some help would be really appreciated!
EDIT:
Here are some pictures of the resources
Resources:
Grades:
Users Intermediate (emails are censored in this pic):
As you can see, what I'm trying to accomplish is also include the resources that have resourcelocationid = 5 or resourcelocationid = 6 if the user teaches in grades that go from 1-3 or 4-6
Have you tryed this way:
SELECT RESOURCEID, RESOURCENAME, RESOURCEDESCRIPTION,
T3.RESOURCELOCATIONNAME, T2.RESOURCESTATUSNAME,
T2.RESOURCESTATUSDESCRIPTION, T2.RESOURCESTATUSID
FROM resource T1
INNER JOIN resource_status T2 USING(RESOURCESTATUSID)
INNER JOIN resource_location T3 USING(RESOURCELOCATIONID)
INNER JOIN grade USING(RESOURCELOCATIONID)
WHERE T1.RESOURCELOCATIONID IN (
SELECT DISTINCT RESOURCELOCATIONID FROM grade G
INNER JOIN users_intermediate UI
ON G.GRADEID = UI.GRADEID
WHERE USERID = "%s"
)
AND (
T1.RESOURCESTATUSID = 1
OR (
T1.RESOURCELOCATIONID = 5
AND (
UNIQUERESOURCES = 1 AND GRADEID >= 1 AND GRADEID <= 12
)
)
OR (
T1.RESOURCELOCATIONID = 6
AND (
UNIQUERESOURCES = 2 AND GRADEID >= 13 AND GRADEID <= 24
)
)
)
Not seeing sample data and confirming true context of your data and expected output, I would like to mentally describe via transitive association.
User "A" is associated with class/grade 1,2 and 3.
Looking into the Grade table, you find User "A" has grade information pointing to Locations "LH", "LR" and "LX" (arbitrary as to not confuse a location with a grade of 1-3 OR 4-6 (or other as later needed)).
Since we know the qualified "Locations", User "A" has access to ANYTHING found within the "LH", "LR" and "LX" locations.
Now, because the ResourceLocationID is in both the Resource_Location and the Resource table, the Grade table can actually join to each directly as the resource location table is nothing more than a lookup to get a descriptive name of where it is. The multiple things IN the room are the resources.
So, the only thing my inner prequery "QualGroups" does, is get a list of the UniqueResources groups (either 1 or 2) a user has access to. The next level is to get all DISTINCT locations under that 1 or 2 status. Because IF a user is access for group 1 at location "LH" AND class group 2 at location "LH", you do not want duplicated resources for location "LH". I am getting the location name while I am at it. (result alias QualLocations)
Now, I can get the resources for those distinct qualified locations
SELECT
QualLocations.ResourceLocationID,
QualLocations.ResourceLocationName,
R.ResourceID,
R.ResourceName,
R.ResourceDescription,
R.ResourceStatusID
from
( SELECT distinct
RL.ResourceLocationID,
RL.ResourceLocationName
from
grade G2
JOIN ( select distinct
G.UniqueResources
from
users_intermediate UI
JOIN grade G
ON UI.GradeID = G.GradeID
where
UI.UserID = "%s" ) QualGroups
ON G2.UniqueResources = QualGroups.UniqueResources
JOIN Resource_Location RL
ON G2.ResourceLocationID = RL.ResourceLocationID )
as QualLocations
JOIN Resource R
ON QualLocations.ResourceLocationID = R.ResourceLocationID
Now, if you ONLY CARE about a very specific classification group, UPDATE the inner-most query joining the "Grade G" table to include the unique resource you are looking for... in this case either 1 or 2
JOIN grade G
ON UI.GradeID = G.GradeID
AND G.UniqueResource = 1 (or 2 if you only wanted 4th-6th grade)
Hope this helps you on your way.
Aside from posted question above, if you change your "UniqueResource" to have a numeric value of the specific GRADE it is vs the verbiage description of the grade name, the AND clause above could be simplified to something like
AND G.UniqueResource IN ( 1, 2, 3 ) // for only grades 1-3
AND G.UniqueResource BETWEEN 1 and 6 // ex: for grades 1-6
AND G.UniqueResource > 6 // for any grade above 6th grade
I've tried everything to figure this out but I can't get the correct total. My attempts either add all the records and not just the latest ones or I only get the first record.
My first table: hubs
hubID hubName
1 hub1
2 hub2
My second table: hub_reports
reportID hubID date health school
1 1 2012-04-27 467 322
2 2 2012-04-23 267 22
3 1 2012-01-20 176 623
So what you see is 2 tables, one with the organizations name and other info and the second with the reports that each organization submits quarterly. I want to list all the organizations and their latest report. At the bottom of the table I want to add all the available health kits and school kits that are currently available.
Here's the code I'm using right now to display all the organizations and their latest reports.
SELECT * FROM (SELECT hubName, date, health, school FROM hub_reports,
hubs WHERE hub_reports.hubID = hubs.hubID ORDER BY date DESC) AS Total
GROUP BY hubName
This seems to work but when I try the same tactic to get the SUM of the health and school columns I don't get the right answer.
SELECT SUM(health) FROM (SELECT hubName, date, health FROM
hub_reports, hubs WHERE hub_reports.hubID = hubs.hubID ORDER BY date
DESC) AS Total GROUP BY hubName
I tried other using a LEFT JOIN approach that I found on another forum but it didn't seem to work any better. But I maybe I wasn't doing it right.
Please help!
I just encountered a similar problem in a project of mine. A variation of this query worked for me. Hope it is helpful to you.
SELECT hubs.hubName, hub_reports.*,
SUM(hub_reports.health) AS ttl_health,
SUM(hub_reports.school) AS ttl_school
FROM hubs, hub_reports
WHERE hub_reports.hubID = hubs.hubID
GROUP BY hub_reports.hubID
ORDER BY hub_reports.date DESC
Here's the PHP:
$rs = mysql_query( 'SELECT hubs.hubName, hub_reports.*,
SUM(hub_reports.health) AS ttl_health,
SUM(hub_reports.school) AS ttl_school
FROM hubs, hub_reports
WHERE hub_reports.hubID = hubs.hubID
GROUP BY hub_reports.hubID
ORDER BY hub_reports.date DESC' );
$grand_total['school']=0;
$grand_total['health']=0;
while ( $row = mysql_fetch_assoc( $rs ) ){ // Step through each hub
echo "{$row['hubName']} shows {$row['ttl_school']} total school, {$row['ttl_health']} total health";
$grand_total['school'] += $row['ttl_school'];
$grand_total['health'] += $row['ttl_health'];
}
echo "Grand Total School: {$grand_total['school']}, Grand Total Health: {$grand_total['health']}";
You're likely looking for the MAX() function.
Try this:
SELECT h.hubID, h.hubname, MAX(hr.date) as hrdate, SUM(hr.health) as health, SUM(hr.school) as school
FROM hubs h
LEFT JOIN hub_reports hr ON hr.hubID = h.hubID
GROUP BY h.hubID
Edit
You want the MAX date so it only returns the most recent entry (assuming your entries are entered by date, of course).
I am doing a web-based application in php for my university and I need to show how many students are taking some courses at the same time so they can avoid scheduling conflicts.
This my schema:
studentID course grade program
324532 csc232 0 computer science
I am using php and this is the SQL query. I put grade 0 because he/she taking the course right now.
$result = mysql_query("SELECT s1.course AS c1 , s2.course AS c2 ,count(*) AS count
FROM student s1 ,student s2
WHERE s1.studentID = s2.studentID
AND s1.course!=s2.course AND s1.grade='0' AND s2.grade='0' GROUP BY s1.course,s2.course");
The answer I got is like this:
cscs321 csci322 6 // there is 6 students taking this two courses together
csci321 csci113 4 // there is 4 students taking these two subjects together
The problem is that I got some repeated results. For example csci321, csc322
is the same as csci322 and csci321.
How can I avoid this repetition?
You could try this one:
SELECT
s1.course AS c1,
s2.course AS c2,
count(s2.studentID) AS count
FROM student s1
JOIN student s2 ON (
s1.studentID = s2.studentID
AND s1.course<s2.course -- <-- this line is important
AND s1.grade='0'
AND s2.grade='0'
)
GROUP BY
s1.course,
s2.course;
The idea is to "sort" the courses per line, so that
csci321, csc322
and
csc322, csci321
are considered the same, because csc233 < csci321
You should use SUM instead of COUNT because you want the sum of students and not the count.