I have 4 tables and I want to select the information from these tables using one query.
I have a table name
tbl_marketing
db_maid db_client db_status db_process
4 test done ddd
tbl_meeting
db_meetingid db_meetingsubject db_mid
1 test 4
tbl_phonecall
db_phid db_subject db_mid
1 ggg 4
2 fff 4
tbl_email
db_eid db_email db_mid
1 xxx 4
Remark: this is an example of my 4 tables. My tables contain more columns
db_mid is the id of tbl_marketing
I want to select all information without repetition
I use this query:
select
marketing.*,
meeting.db_meetingid,meeting.db_meetingsubject,meeting.db_sd,meeting.db_dd,meeting.db_duration as meetingDuration,meeting.db_place,meeting.db_mom,meeting.db_momattache,meeting.db_status as meetingStatus,meeting.db_nextmeeting,meeting.db_lastmeeting,meeting.db_attendees,meeting.db_note as meetingNote,meeting.db_mid,
phonecall.db_phid,phonecall.db_subject as phoneSubject,phonecall.db_desc as phoneDesc,phonecall.db_nextdate,phonecall.db_doc,phonecall.db_duration as phoneDuration,phonecall.db_phstatus,phonecall.db_pnote,phonecall.db_client as phoneClient,phonecall.db_crf,phonecall.db_callto,phonecall.db_phone as phonecallPhone,phonecall.db_logs as phoneLogs,phonecall.db_mid,phonecall.db_dateedit as phoneEdit,phonecall.db_phdate,
email.db_eid,email.db_edate,email.db_esubject,email.db_edesc,email.db_erf,email.db_emailto,email.db_email as eEmail,email.db_dos,email.db_dor,email.db_estatus,email.db_logs as eLogs,email.db_note as eNote,
location.db_location as location,
location.db_lid,
company.db_company as com,
company.db_coid,
subcompany.db_subid,
subcompany.db_subcompany as sub,
user.db_uid,
concat(user.db_fname,' ' ,user.db_lname) as tr,
subj.db_subjid,
subj.db_subject as s
from tbl_marketing as marketing
left join tbl_location as location
on
marketing.db_location=location.db_lid
left join tbl_meeting as meeting
on
marketing.db_maid=meeting.db_mid
left join tbl_phonecall as phonecall
on
marketing.db_maid=phonecall.db_mid
left join tbl_email as email
on
marketing.db_maid=email.db_mid
left join tbl_company as company
on
marketing.db_companyname=company.db_coid
left join tbl_subcompany as subcompany
on
marketing.db_subcompany=subcompany.db_subid
left join tbl_user as user
on
marketing.db_transfered=user.db_uid
left join tbl_subject as subj
on
phonecall.db_subject=subj.db_subjid
where
marketing.db_maid='$read'
and
meeting.db_mid='$read'
and
email.db_mid='$read'
and
phonecall.db_mid='$read'
I use this query to select the information but when I have 2 rows, the same db_mid as tbl_phonecall in the example, then the information is duplicated as follows:
table marketing
1 test 4
1 test 4
table phonecall
1 ggg 4
2 fff 4
table meeting
1 test 4
1 test 4
table email
1 xxx 4
1 xxx 4
As visible above all tables have a duplicate value without phonecall because he have 2 rows I want to show all the information without this repetition
if I use group by mid I don't receive the second information in tbl_phonecall
$rows=array();
while($rows=mysqli_fetch_array($sql)){
$row[]=$rows;}
<table>
foreach($rows as row){
<tr>
<td><?php echo $row['phID'];?></td>
</tr>
}
</table>
output
# subject mid
1 test 4
2 ggg 4
not like this
1,2 test,ggg 4,4
If you only have duplicates in the phonecall table, the following should work. If other left joined tables can have duplicates, just add GROUP_CONCAT as needed.
select
marketing.*,
meeting.db_meetingid,
meeting.db_meetingsubject,
meeting.db_sd,
meeting.db_dd,
meeting.db_duration as meetingDuration,
meeting.db_place,
meeting.db_mom,
meeting.db_momattache,
meeting.db_status as meetingStatus,
meeting.db_nextmeeting,
meeting.db_lastmeeting,
meeting.db_attendees,
meeting.db_note as meetingNote,
meeting.db_mid,
GROUP_CONCAT(phonecall.db_phid) as phID,
GROUP_CONCAT(phonecall.db_subject) as phoneSubject,
GROUP_CONCAT(phonecall.db_desc) as phoneDesc,
GROUP_CONCAT(phonecall.db_nextdate) as phNextDate,
GROUP_CONCAT(phonecall.db_doc) as phDoc,
GROUP_CONCAT(phonecall.db_duration) as phoneDuration,
GROUP_CONCAT(phonecall.db_phstatus) as phStatus,
GROUP_CONCAT(phonecall.db_pnote) as phPNote,
GROUP_CONCAT(phonecall.db_client) as phoneClient,
GROUP_CONCAT(phonecall.db_crf) as phCrf,
GROUP_CONCAT(phonecall.db_callto) as phCallTo,
GROUP_CONCAT(phonecall.db_phone) as phonecallPhone,
GROUP_CONCAT(phonecall.db_logs) as phoneLogs,
GROUP_CONCAT(phonecall.db_mid) as phMid,
GROUP_CONCAT(phonecall.db_dateedit) as phoneEdit,
GROUP_CONCAT(phonecall.db_phdate) as phdate,
email.db_eid,
email.db_edate,
email.db_esubject,
email.db_edesc,
email.db_erf,
email.db_emailto,
email.db_email as eEmail,
email.db_dos,
email.db_dor,
email.db_estatus,
email.db_logs as eLogs,
email.db_note as eNote,
location.db_location as location,
location.db_lid,
company.db_company as com,
company.db_coid,
subcompany.db_subid,
subcompany.db_subcompany as sub,
user.db_uid,
concat(user.db_fname,' ' ,user.db_lname) as tr,
subj.db_subjid,
subj.db_subject as s
from tbl_marketing as marketing
left join tbl_location as location
on marketing.db_location=location.db_lid
left join tbl_meeting as meeting
on marketing.db_maid=meeting.db_mid
left join tbl_phonecall as phonecall
on marketing.db_maid=phonecall.db_mid
left join tbl_email as email
on marketing.db_maid=email.db_mid
left join tbl_company as company
on marketing.db_companyname=company.db_coid
left join tbl_subcompany as subcompany
on marketing.db_subcompany=subcompany.db_subid
left join tbl_user as user
on marketing.db_transfered=user.db_uid
left join tbl_subject as subj
on phonecall.db_subject=subj.db_subjid
where marketing.db_maid='$read' and
meeting.db_mid='$read' and
email.db_mid='$read' and
phonecall.db_mid='$read'
GROUP BY meeting.db_mid
Related
I have the following tables:
StudentProfile in which I have fields RollNumber, Major
StudentEnrollment in which I have fields RollNumber, CourseCode, Section, Semester
DepartmentFees in which I have fields DepartmentName, Semester, Fees
What I'm trying to do it to find the fees a student has to pay in a particular semester. The problem is the StudentEnrollment table has multiple repeated values which is making it difficult to find the exact fees.
My StudentEnrollment table is like this:
RollNO |CourseCode |Section |Semester
-----------+---------------+------------+------------
ST-0001 |BIOL 300 |A |Fall 2018
ST-0001 |BIOL 500 |A |Spring 2018
ST-0001 |BIOL 450 |B |Spring 2018
ST-0001 |BIOL 475 |A |Spring 2018
ST-0002 |CHEM 500 |A |Spring 2018
ST-0002 |CHEM 450 |B |Spring 2019
Now with repeated values of roll number and Semester how do I get the correct answer.
If I use GROUP BY (StudentEnrollment.RollNo) , the roll number does not repeat I cant get all the semesters the student has attended and if I use GROUP BY (StudentEnrollment.RollNo) I dont get all the student's rollnumbers in the semsester.
Initially I tried using
Select
a.RollNo,
b.Semester,
c.Fees
FROM StudentProfile a
LEFT JOIN StudentEnrollment b ON b.RollNo = c.RollNo
LEFT JOIN DepartmentFees C ON c.DepartmentName = a.Major //AND maybe join semester?
But it doesn't seem to work. What can I try next?
Just add the columns to the Group by clause:
Select
a.RollNo,
b.Semester,
sum(c.Fees) AS 'total'
FROM StudentProfile a
LEFT JOIN StudentEnrollment b ON b.RollNo = c.RollNo
LEFT JOIN DepartmentFees C ON c.DepartmentName = a.Major //AND maybe join semester?
GROUP BY
a.RollNo,
b.Semester
Since you have mention b.Semester, c.Fees in select statement, so to do group by RollNo and Semester, add a.RollNo and b.Semester in GROUP BY clause, I have used "JOIN" instead of "LEFT JOIN" cause use JOIN/INNER JOIN when you want to return only records having pair on both sides, and you’ll use LEFT JOIN when you need all records from the “left” table, no matter if they have pair in the “right” table or not.
Select
a.RollNo,
b.Semester,
sum(c.Fees) AS 'total'
FROM StudentProfile a
JOIN StudentEnrollment b ON b.RollNo = c.RollNo
JOIN DepartmentFees C ON c.DepartmentName = a.Major
GROUP BY
a.RollNo,
b.Semester
I'm trying to find a patient's appointments and messages count. My table records are like below 3 table patient, appointments and messages
Patient table
pid fname lname
1 john sid
2 rother ford
3 megan rough
4 louis kane
appointments table
id pid appointment_date
1 1 2015-08-04
2 2 2015-08-05
3 1 2015-08-06
4 1 2015-08-07
5 3 2015-08-07
6 2 2015-08-08
7 4 2015-08-13
8 1 2015-08-12
Messages table
id pid description message_date
1 2 join 2015-08-04
2 2 update 2015-08-05
3 3 join 2015-08-05
4 4 update 2015-08-10
5 3 test 2015-08-07
So if write query to find counts i'm getting wrong values
SELECT pd.fname,pd.lname , pd.pid, COUNT( a.id ) AS app_cnt, COUNT( m.id ) AS mes_cnt
FROM patient pd
LEFT OUTER JOIN appointments a ON a.pid = pd.pid
LEFT OUTER JOIN messages m ON m.pid = pd.pid
GROUP BY pd.pid
ORDER BY pd.pid
fname lname pid app_cnt mes_cnt
john sid 1 4 0
rother ford 2 4 4
megan rough 3 2 2
louis kane 4 1 1
Here pid 1 have 4 appointments and 0 messages, pid 2 have 2 appointments and 2 messages but getting wrong values.
Can someone please help to resolve this issue. I'm not interested in writing sub queries for this.
Functionality looks simple but I'm really facing problem for writing query.
Anymore suggestions please.
After thoroughly analysing your problem and tables, It cannot be done directly using simple query as LEFT OUTER JOIN is returning some superfluous records, that's why to filter it, you will have to use temporary table and modify the query as:
Select temp.fname, temp.lname, temp.pid, a_count, count(m.pid) as m_count from
(SELECT fname,lname,pd.pid, count(a.pid) as a_count
FROM patients pd
LEFT OUTER JOIN appointments a ON a.pid = pd.pid group by pd.pid) temp
LEFT OUTER JOIN messages m ON m.pid = temp.pid
group by temp.pid
Explanation:
It will join patients and appointments table and group them by pid so that messages from message table do not repeat for each patients.pid.
The wrong result is as a result of left outer join as it is giving wrong results for this query
SELECT *
FROM patients pd
LEFT OUTER JOIN appointments a ON a.pid = pd.pid
LEFT OUTER JOIN messages m ON m.pid = pd.pid
Since we need to limit the results of first two joins, hence temporary table is necessary.
I have 4 tables as below
Table1: restos
Structure:
resu_id resu_name resu_address
-------------------------------------
1 ABC Exapmple
2 DEF Example
3 GHD Example
Table2:foodtype
Structure:
id typename
---------------
12 Indian
23 Punjabi
Table3: resto_foodtypes
Structure:
resu_id foodty_id
--------------------
1 12
2 23
3 12
Table4: discnts
Structure:
id resu_id amt_dscPer(%age discount)
---------------------------
19 1 15
20 2 25
Now i want to display the restaurant along with discounts available for the restauarant.
Currently restaurants are getting displayed but for the restaurant not present in discnts table are returning null values from discnts table.
below is the query that m using
SELECT * from `restos` r join resto_foodtypes rf on rf.resu_id = r.resu_id
join foodtype f on rf.foodty_id = f.id left join discnts dcfm on
r.resu_id= dcfm.resu_id where true;
I want that the restaurants that are not present in discnts table should not be included in resultset. For e.g. resu_id=3 is not present in discnts table.
To exclude results that have no entry in discnts table, use a INNER JOIN instead of a LEFT JOIN.
To include these results, but have a 0 displayed (instead of the defaults NULL), you can use IFNULL(expr, 0) function:
SELECT
r.resu_name AS Name,
f.typename AS Food,
IFNULL(dcfm.amt_dscPer, 0) AS Discount
FROM `restos` r
JOIN resto_foodtypes rf ON rf.resu_id = r.resu_id
JOIN foodtype f ON rf.foodty_id = f.id
LEFT JOIN discnts dcfm ON r.resu_id= dcfm.resu_id;
IFNULL returns the first parameter if it is not null, the second if expr is indeed null.
I have 3 tables office, Computer and Maintain. Office just list of offices, computers belongs to office as well as has many Maintains.
I want to LEFT join all tables with just the latest entry from Maintain table. The code below works but it just group the oldest entry in the maintain.
SELECT `Computer`.`id`, `Computer`.`control`, `Computer`.`operator`, `Computer`.`datePurchased`, `Computer`.`type`, `Computer`.`property`, `Computer`.`printer`, `Computer`.`scanner`, `Computer`.`osx`, `Computer`.`applications`, `Computer`.`licence`, `Computer`.`isStandAlone`, `Computer`.`isInternet`, `Computer`.`isNetwork`, `Computer`.`generalStatus`, `Computer`.`ip_address`, `Computer`.`mac_address`, `Computer`.`user_id`, `Computer`.`office_id`, `Computer`.`created`, `Computer`.`modified`, `Computer`.`deleted`, `Office`.`id`, `Office`.`description`, `Office`.`main_office`, `Maintain`.`id`, `Maintain`.`dateEncoded`, `Maintain`.`findings`, `Maintain`.`checkedBy`, `Maintain`.`remarks`, `Maintain`.`computer_id`, `Maintain`.`created`, `Maintain`.`modified`, `Maintain`.`user_id` FROM `computers`.`computer` AS `Computer`
LEFT JOIN `computers`.`office` AS `Office`
ON (`Office`.`id` = `Computer`.`office_id`)
LEFT JOIN `computers`.`maintain` AS `Maintain`
ON (`Computer`.`id` = `Maintain`.`computer_id`)
LEFT JOIN (SELECT MAX(dateEncoded) maxDate, findings FROM maintain GROUP BY computer_id) AS `P2`
ON (`Maintain`.`dateEncoded` = `p2`.`maxDate`)
WHERE `Office`.`main_office` LIKE '%CVPH MON%'
GROUP BY `Computer`.`id`
ORDER BY `Office`.`description` ASC
SAMPLE
OFFICE
1 AAAA
2 BBBB
COMPUTER
id name office_id
1 CP1 1
2 CP2 1
3 CP3 2
Maintain
id description date computer_id
1 Fix 06/20/2014 1
2 Fix 06/11/2014 1
3 Fix 06/12/2014 2
4 Fix 06/15/2014 2
Result if query on computer=CP1 should be
Office Computer_name Maintain_desc Date
AAA CP1 Fix 06/20/2014 <- Latest entry in maintain
You can do so
SELECT `c`.`id`,
`c`.`name`,
`c`.`office_id` ,
`o`.`name` office_name,
`m`.`date`,
`m`.`description`
FROM `computer` AS c
LEFT JOIN `office` AS `o`
ON (`o`.`id` = `c`.`office_id`)
LEFT JOIN `maintain` AS m
ON (`c`.`id` = `m`.`computer_id`)
INNER JOIN
(SELECT computer_id,MAX(`date`) maxdate
FROM maintain
GROUP BY computer_id ) t
ON(m.`date`=t.maxdate AND m.computer_id= t.computer_id)
WHERE `c`.`name` ='CP1' ... more conditions
Demo
I have a table ('names') which includes data related with other data in other tables relying on ids. For example:
*Names table
id | name | predecessor | successor | house | birthplace
-----------------------------------------------------------------
10 Bayezid II 9 11 4 NULL
11 Selim I 10 12 4 5
12 Suleiman 11 13 4 61
*Houses table
id | house
--------------
4 House of Osman
*Places table
id | place
--------------
5 Amasya
61 Trabzon
What I'm trying to accomplish is to construct a query which results in returning whole information depending on the id, like:
{"result":[{
"id":"11",
"name":"Selim I",
"predecessor": "Bayezid II",
"successor": "Suleiman",
"house":"House of Osman",
"birthplace":"Amasya"
}]}
So, the name of the house and the birthplace are brought from other tables ('houses', 'places') whereas the predecessor and the successor are from the same table. I need help constructing this query. Thank you.
Just self-join a couple times, once to get the predecessor's row (aliased n0 below), and once more for the successor's (n2):
SELECT n1.id, n1.name, n0.name AS predecessor, n2.name AS successor
FROM names n1
LEFT JOIN names n0 ON n1.predecessor = n0.id
LEFT JOIN names n2 ON n1.successor = n2.id
SQL Fiddle demo
Joining to get the house and birthplace are left as an exercise for the reader.
Try this:
select n.id,
n.name,
n1.name as predecessor,
n2.name as successor,
h.house,
p.place
from names n
inner join names n1 on n.id = n1.predecessor
inner join names n2 on n.id = n2.successor
left join Houses h on n.house = h.id
left join Place p on n.birthplace = p.id
where n.id = 11