I am exposing my concern to you.
There are "demande_psy" and "consultant" tables. Each "demande_psy" record can relate to several "consultants" records, and each "consultant" record can relate to several "demande_psy" records, according to a "statut". This is the reason why, the primary key of the "demande_psy_consultant" link table (many to many relation table) is composed of: "id_demande_psy", "id_consultant", "statut". By querying the database , I need to retrieve a list of demande_psy and their priority statut, according to these 3 rules:
If among the same demand_psy, I have at least one AFFECTED status => my request line must display the "Affected" status
Otherwise, if among the same demande_psy, I have at least one status ACCEPTED => my demande_psy line must display "Accepted"
Otherwise my demande_psy line should show "Sent"
Here my tables creation code :
CREATE TABLE `demande_psy` (
`id` int(10) UNSIGNED NOT NULL,
`titre` varchar(255) NOT NULL,
`detail` text NOT NULL,
`sms` text NOT NULL,
`created_at` datetime NOT NULL,
`modified_at` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `demande_psy` (`id`, `titre`, `detail`, `sms`, `created_at`)
VALUES (1, 'Test demande', 'bla bla bla bla', 'qsdf\r\nqsdf\r\n', '2021-03-18 17:23:59');
ALTER TABLE `demande_psy` ADD PRIMARY KEY (`id`);
ALTER TABLE `demande_psy` MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
CREATE TABLE `consultant` (
`id` int(11) UNSIGNED NOT NULL,
`prenom` varchar(100) DEFAULT NULL,
`nom` varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `consultant` (`id`, `prenom`, `nom`) VALUES
(52, 'Michel', 'Moral (Somica - Undici)'),
(55, 'Patrick', 'Amar');
ALTER TABLE `consultant` ADD PRIMARY KEY (`id`);
ALTER TABLE `consultant` MODIFY `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=56;
CREATE TABLE `demande_psy_consultant` (
`id_demande_psy` int(10) UNSIGNED NOT NULL,
`id_consultant` int(10) UNSIGNED NOT NULL,
`statut` enum('SENT','ACCEPTED','AFFECTED') NOT NULL,
`created_at` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `demande_psy_consultant` (`id_demande_psy`, `id_consultant`,
`statut`, `created_at`) VALUES
(1, 52, 'SENT', '2021-03-18 17:39:59'),
(1, 55, 'ACCEPTED', '2021-03-18 19:05:45');
ALTER TABLE `demande_psy_consultant` ADD PRIMARY KEY (`id_demande_psy`,`id_consultant`,`statut`);
ALTER TABLE `demande_psy_consultant`
ADD CONSTRAINT `fk_consultant` FOREIGN KEY (`id_consultant`) REFERENCES `consultant` (`id`),
ADD CONSTRAINT `fk_demande_psy` FOREIGN KEY (`id_demande_psy`) REFERENCES `demande_psy` (`id`);
Here a simplified example :
demande_psy
-----------
1 toto
6 titi
consultant
----------
15 Marc
88 Jean
demande_psy_consultant
----------------------
1 15 SENT
1 62 SENT
1 88 ACCEPTED
1 88 AFFECTED
6 88 SENT
6 15 SENT
==> EXPECTED RESULT
---------------------------------------------------
1 88 AFFECTED (according to the 3 rules)
6 15 SENT
And now, here is my sql query:
SELECT
DPC.id_demande_psy,
DPC.id_consultant,
(CASE
WHEN (SELECT count(DPC.statut) FROM demande_psy_consultant DPC WHERE DPC.statut = "AFFECTED")>0 THEN "AFFECTED"
WHEN (SELECT count(DPC.statut) FROM demande_psy_consultant DPC WHERE DPC.statut = "ACCEPTED")>0 THEN "ACCEPTED"
ELSE "SENT"
END) as statutComputed
FROM demande_psy_consultant DPC
GROUP BY DPC.id_demande_psy
With it, I obtain :
MY (BAD) RESULT
---------------
1 15 AFFECTED
6 15 AFFECTED
So I struggle a bit to correct it to obtain the desired result If anyone has an idea, I'm interested
thank you !
Related
Actually, i don't know that what should be the title of the question.
I have two table which schema define as below:
**Table 1 (organization_master)**:
CREATE TABLE `organization_master` ( `organization_id` int(11) NOT NULL, `parent_organization_id` int(11) DEFAULT NULL, `organization_name` varchar(150) NOT NULL, `c_user_id` int(11) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `organization_master` (`organization_id`, `parent_organization_id`, `organization_name`, `c_user_id`) VALUES
(119, NULL, 'Patel-Apps', 220),
(183, 119, 'Patel-Apps sub 1', 220),
(184, 119, 'Patel-Apps sub 2', 220),
(250, 247, 'Patel-Apps2', 222);
ALTER TABLE `organization_master` ADD PRIMARY KEY (`organization_id`), ADD KEY `organization_name` (`organization_name`), ADD KEY `c_user_id` (`c_user_id`);
ALTER TABLE `organization_master` MODIFY `organization_id` int(11) NOT NULL AUTO_INCREMENT;
**Table 2 (organization_assigned_user)** :
CREATE TABLE `organization_assigned_user` ( `organization_assigned_user_id` int(11) NOT NULL, `organization_id` int(11) DEFAULT NULL, `user_id` int(11) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `organization_assigned_user` (`organization_assigned_user_id`, `organization_id`, `user_id`) VALUES (29, 250, 219),(30, 250, 220);
ALTER TABLE `organization_assigned_user` ADD PRIMARY KEY (`organization_assigned_user_id`), ADD KEY `user_id` (`user_id`), ADD KEY `organization_id` (`organization_id`);
ALTER TABLE `organization_assigned_user` MODIFY `organization_assigned_user_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=31;
when i run below query it give me output as below:
SELECT om.organization_id, om.parent_organization_id, om.organization_name FROM `organization_master` AS om LEFT JOIN organization_assigned_user AS oau ON om.organization_id = oau.organization_id WHERE om.c_user_id =220 OR oau.user_id =220 GROUP BY om.organization_id
organization_id parent_organization_id organization_name
119 NULL Patel-Apps
183 119 Patel-Apps sub 1
184 119 Patel-Apps sub 2
250 247 Patel-Apps2
Now, my question is that i don't want the rows which parent_organization_id exists in organization_id column. i.e 199 parent_organization_id exists in organization_id. so my out put should be like like below.
organization_id parent_organization_id organization_name
119 NULL Patel-Apps
250 247 Patel-Apps2
You Can try this
SELECT om.organization_id, om.parent_organization_id, om.organization_name
FROM `organization_master` AS om LEFT JOIN organization_assigned_user AS oau
ON om.organization_id = oau.organization_id
WHERE om.c_user_id =220 OR oau.user_id =220
AND Exists (SELECT 1 FROM `organization_master` o
WHERE o.organization_id = om.organization_id
AND o.parent_organization_id <> om.organization_id)
GROUP BY om.organization_id;
So, what i have is a system using MySQL for storage that should be storing donations made by people (donators). Donation is entered into system by authorized user.
Here are create tables for all 4 tables:
CREATE TABLE `donator` (
`DONATOR_ID` int(11) NOT NULL AUTO_INCREMENT,
`DONATOR_NAME` varchar(50) NOT NULL,
`STATUS` char(1) COLLATE NOT NULL DEFAULT 'A',
PRIMARY KEY (`DONATOR_ID`)
)
CREATE TABLE `user` (
`USER_ID` int(11) NOT NULL AUTO_INCREMENT,
`USERNAME` varchar(100) NOT NULL,
`PASSWORD` varchar(200) NOT NULL,
`TYPE` char(1) COLLATE NOT NULL,
PRIMARY KEY (`USER_ID`)
)
CREATE TABLE `sif_res` (
`RES_ID` int(11) NOT NULL AUTO_INCREMENT,
`RES_NAME` varchar(50) NOT NULL,
`MON_VAL` double NOT NULL,
PRIMARY KEY (`RES_ID`)
)
CREATE TABLE `donations` (
`DONATION_ID` int(11) NOT NULL AUTO_INCREMENT,
`RESOURCE` int(11) NOT NULL,
`AMOUNT` int(11) NOT NULL,
`DONATOR` int(11) NOT NULL,
`ENTRY_DATE` datetime NOT NULL,
`ENTERED_BY_USER` int(11) NOT NULL,
PRIMARY KEY (`DONATION_ID``),
KEY `fk_resurs` (`RESOURCE``),
KEY `fk_donator` (`DONATOR``),
KEY `fk_user` (`ENTERED_BY_USER``),
CONSTRAINT `fk_1` FOREIGN KEY (`DONATOR`) REFERENCES `donator` (`DONATOR_ID`) ON UPDATE CASCADE,
CONSTRAINT `fk_2` FOREIGN KEY (`RESOURCE`) REFERENCES `sif_res` (`RES_ID`) ON UPDATE CASCADE,
CONSTRAINT `fk_3` FOREIGN KEY (`ENTERED_BY_USER`) REFERENCES `user` (`USER_ID`) ON UPDATE CASCADE
)
As you can see, I have a list of donators, users and resources that can be donated.
Now, I want to display all donators' name and their id's, however in third column I would like to display their balance (sum of all of items they donated) - this is calculated with
donation.AMOUNT * sif_res.MON_VAL
for each donation
The SQL SELECT I have written works, however donators that haven't donated anything are left out (they are not matched by JOIN). I would need that it displays everyone (with STATUS!=D) even if they don't have any entries (in that case their balance may be 0 or NULL)
This is my SQL i have written:
SELECT DONATOR_ID
, DONATOR_NAME
, round(SUM(d.AMOUNT * sr.MON_VAL)) as BALANCE
from donator c
join donations d on c.DONATOR_ID=d.DONATOR
join sif_res sr on sr.RES_ID=d.RESOURCE
where c.STATUS!='D'
group by DONATOR_ID, DONATOR_NAME
So, if i execute next sentences:
INSERT INTO donator(DONATOR_NAME, STATUS) VALUES("John", 'A'); //asigns id=1
INSERT INTO donator(DONATOR_NAME, STATUS) VALUES("Willie", 'A'); //asigns id=2
INSERT INTO user (USERNAME, PASSWORD, TYPE) VALUES("user", "pass", 'A'); //asigns id=1
INSERT INTO sif_res(RES_NAME, MON_VAL) VALUES("Flour", "0.5"); //asigns id=1
INSERT INTO donations(RESOURCE, AMOUNT, DONATOR, ENTRY_DATE, ENTERED_BY_USER) VALUES(1, 100, 1, '2.2.2017', 1);
I will get output (with my SELECT sentence above):
DONATOR_ID | DONATOR_NAME | BALANCE
--------------------------------------------
1 | John | 50
What i want to get is:
DONATOR_ID | DONATOR_NAME | BALANCE
--------------------------------------------
1 | John | 50
2 | Willie | 0
I have tried all version of joins (left, right, outer, full,..) however none of them worked for me (probably because i was using them wrong)
If it was just the problem of unmatched data i would be able to solve it, however the aggregate function SUM and another JOIN make it all more complicated
Using a left outer join on the second two tables should do the trick:
SELECT c.DONATOR_ID
, c.DONATOR_NAME
, ifnull(round(SUM(d.AMOUNT * sr.MON_VAL)),0) as BALANCE
from donator c
left outer join donations d on c.DONATOR_ID=d.DONATOR
left outer join sif_res sr on sr.RES_ID=d.RESOURCE
where c.STATUS!='D'
group by DONATOR_ID, DONATOR_NAME
I also wrapped the BALANCE expression in ifnull to display 0 instead of null.
I have a set of tables containing staff memebers' secondary specialities in different formats. Actually, only few primary specialities allow a person to have a secondary speciality.
I make a UNION view, combining the secondary specialities in this way and it is working fine:
SELECT tpl.id, tpl.speciality, 20 as gr FROM tpath_list tpl
UNION ALL
SELECT tlt.id, tlt.lab_type as speciality, 11 as gr FROM tlab_types tlt
UNION ALL
SELECT til.id, til.speciality, 10 as gr FROM tinstrumental_list til
Field gr contains the index field of the primary specialities (10, 11 and 20) allowing to have a secondary speciality. All other specialities (with id 1, 2, 3 etc.) do not have secondary ones.
I receive something like this...
I can now fetch data from the created view using WHERE gr=:n.
How can I modify the view so that fetching data from it using WHERE gr=:n (1, 2, 3 etc.) clause will give me a single record id=1 speciality="Not specified" gr=n
Appended on comments of the community:
I need to fetch all the records if :n IN(10,11,20) that are present in the tables and presented by the view. For example, 3 records listed in the picture for :n=20. Only if :n NOT IN(10,11,20) I need an additional (single) record absenting from the tables (and the view). Please, note that records with gr IN(10,11,20) have got the id=1 and speciality='Not specified'.
Appended on request of Jon Tofte-Hansen
Here is an unfiltered view output (without WHERE clause).
If I fetch the view with WHERE gr=20 I get the following (that is what I want):
If with WHERE gr=10 - this set (that is what I want):
If I fetch it with WHERE gr=1 then I woud like to receive a sigle record that is absent in any of the tables used for view creation. I wish to get this output but do not know how to:
Here is the structure of the tables if it might help:
DROP TABLE IF EXISTS `tspecialities_list`;
CREATE TABLE `tspecialities_list` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`speciality` varchar(30) NOT NULL DEFAULT '',
PRIMARY KEY (`id`,`speciality`),
KEY `i_by_speciality` (`speciality`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `tlab_types`;
CREATE TABLE `tlab_types` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`lab_type` varchar(255) DEFAULT NULL,
`deleted` smallint(5) unsigned DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `tpath_list`;
CREATE TABLE `tpath_list` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`speciality` varchar(30) NOT NULL DEFAULT '',
PRIMARY KEY (`id`,`speciality`),
KEY `i_by_speciality` (`speciality`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `tinstrumental_list`;
CREATE TABLE `tinstrumental_list` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`speciality` varchar(30) NOT NULL DEFAULT '',
PRIMARY KEY (`id`,`speciality`),
KEY `i_by_speciality` (`speciality`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
It is not entirely clear what you want, but this could be it. Add an extra union that produce all the id's not present in the three tables with secondary specialities:
SELECT tpl.id, tpl.speciality, 20 as gr FROM tpath_list tpl
UNION ALL
SELECT tlt.id, tlt.lab_type as speciality, 11 as gr FROM tlab_types tlt
UNION ALL
SELECT til.id, til.speciality, 10 as gr FROM tinstrumental_list til
UNION ALL
select tsl.id, 'Not specified', tsl.id as gr from tspecialities_list tsl
where tsl.id not in
(SELECT tpl.id FROM tpath_list tpl
UNION
SELECT tlt.id FROM tlab_types tlt
UNION
SELECT til.id FROM tinstrumental_list til)
It seems like you are just asking for the following:
SELECT *
FROM viewname
WHERE speciality='Not specified' and gr=:n
Is there a reason this isn't what you want?
I would like to merge a table that the data comes from 2 differents databases.
I operated as described below:
1 – I have done a dump of the source database table and I get the following insert query:
INSERT INTO `t_vaccination` VALUES (242,NULL,NULL,53,1,'20030528','0','W5770-2',0,'DTP - REVAXIS','A 20130521170623','2013-05-21 17:06:23'),
(243,NULL,NULL,53,1,'20130525','0','',1,'DTP - ','A 20130521170623','2013-05-21 17:06:23'),
(1830,NULL,NULL,50,1,'20080502','3','',0,'DTP - REVAXIS','A 20130521170623','2013-05-21 17:06:23'),
(1831,NULL,NULL,50,1,'20130501','4','',1,'DTP - ','A 20130521170623','2013-05-21 17:06:23'),
(1832,NULL,NULL,50,1,'20080502','3','',0,'PAPILLOMAVIRUS - Gardasil','A 20130521170623','2013-05-21 17:06:23')
the structure of the t_vaccination table is:
CREATE TABLE `t_vaccination` (
`nIdVaccination` INT(10) UNSIGNED NOT NULL,
`nIdVaccin` INT(10) UNSIGNED NULL DEFAULT NULL,
`nIdVacProtocole` INT(10) UNSIGNED NULL DEFAULT NULL,
`nIdPatient` INT(10) UNSIGNED NOT NULL,
`nIdUtilisateur` INT(10) UNSIGNED NULL DEFAULT NULL,
`sDateInjection` VARCHAR(8) NOT NULL DEFAULT '',
`nNumInjection` VARCHAR(45) NOT NULL DEFAULT '0',
`sNumLot` VARCHAR(45) NOT NULL DEFAULT '',
`nRappel` TINYINT(4) NOT NULL DEFAULT '0',
`sLibelle` VARCHAR(255) NOT NULL DEFAULT '',
`sAction` VARCHAR(16) NOT NULL DEFAULT 'A 20080101000000',
`sDH_REPLIC` DATETIME NULL DEFAULT '2010-01-01 00:00:00',
PRIMARY KEY (`nIdVaccination`),
INDEX `NDX_t_vaccination_nIdUtilisateur` (`nIdUtilisateur`),
INDEX `NDX_t_vaccination_nIdVaccin` (`nIdVaccin`),
INDEX `NDX_t_vaccination_nIdVacProtocole` (`nIdVacProtocole`),
INDEX `NDX_t_vaccination_nIdPatient` (`nIdPatient`),
CONSTRAINT `FK_vaccination_nIdUtilisateur_utilisateur` FOREIGN KEY (`nIdUtilisateur`) REFERENCES `t_utilisateur` (`nIdUtilisateur`),
CONSTRAINT `FK_vaccination_nIdVaccin_vaccin` FOREIGN KEY (`nIdVaccin`) REFERENCES `t_vaccin` (`nIdVaccin`)
)
2 - I would like to insert all the rows in the t_vaccination table of the final database without inserting the duplicates rows. the new query run by inserting one row:
INSERT INTO t_vaccination (nIdVaccination, nIdVaccin, nIdVacProtocole, nIdPatient, nIdUtilisateur, sDateInjection, nNumInjection, sNumLot, nRappel, sLibelle, sAction, sDH_REPLIC)
SELECT 251,41,4,53,1,'20030528','0','W5770-2',0,'DTP - REVAXIS','A 20130521170623','2013-05-21 17:06:23' FROM t_vaccination WHERE NOT EXISTS (SELECT nIdVaccin, nIdVacProtocole, nIdPatient, nIdUtilisateur FROM t_vaccination WHERE nIdVaccin = 41 and nIdVacProtocole = 4 and nIdPatient = 53 and nIdUtilisateur =1 ) LIMIT 1
3 - Is it possible to insert rows by group by using insert where not exists because the attempts that i have done failed. here is an example of an an insert that failed:
INSERT INTO t_vaccination (nIdVaccination, nIdVaccin, nIdVacProtocole, nIdPatient, nIdUtilisateur, sDateInjection, nNumInjection, sNumLot, nRappel, sLibelle, sAction, sDH_REPLIC)
SELECT 251,41,4,53,1,'20030528','0','W5770-2',0,'DTP - REVAXIS','A 20130521170623','2013-05-21 17:06:23' FROM t_vaccination WHERE NOT EXISTS (SELECT nIdVaccin, nIdVacProtocole, nIdPatient, nIdUtilisateur FROM t_vaccination WHERE nIdVaccin = 41 and nIdVacProtocole = 4 and nIdPatient = 53 and nIdUtilisateur =1 ) LIMIT 1,
SELECT 243,NULL,NULL,53,1,'20130525','0','',1,'DTP - ','A 20130521170623','2013-05-21 17:06:23' FROM t_vaccination WHERE NOT EXISTS (SELECT nIdVaccin, nIdVacProtocole, nIdPatient, nIdUtilisateur FROM t_vaccination WHERE nIdVaccin = NULL and nIdVacProtocole = NULL and nIdPatient = 53 and nIdUtilisateur =1 ) LIMIT 1
I hope for your help.
Regards
Motti
In my opinion, the simplest way to do what you want is to remove Unique keys/indexes and remove dupes or create a temporary table without those keys. Let's assume you create a temp_t_vaccination table and import all your rows in, you'll then just have to do :
INSERT INTO t_vaccination (field1, field2 ...) SELECT DISTINCT field1, fields2 ... FROM temp_vaccination
ref : http://dev.mysql.com/doc/refman/5.0/en/insert-select.html?ff=nopfpls
I want to subtract between two rows of different table:
I have created a view called leave_taken and table called leave_balance.
I want this result from both table:
leave_taken.COUNT(*) - leave_balance.balance
and group by leave_type_id_leave_type
Code of both table
-----------------View Leave_Taken-----------
CREATE ALGORITHM = UNDEFINED DEFINER=`1`#`localhost` SQL SECURITY DEFINER
VIEW `leave_taken`
AS
select
`leave`.`staff_leave_application_staff_id_staff` AS `staff_leave_application_staff_id_staff`,
`leave`.`leave_type_id_leave_type` AS `leave_type_id_leave_type`,
count(0) AS `COUNT(*)`
from
(
`leave`
join `staff` on((`staff`.`id_staff` = `leave`.`staff_leave_application_staff_id_staff`))
)
where (`leave`.`active` = 1)
group by `leave`.`leave_type_id_leave_type`;
----------------Table leave_balance----------
CREATE TABLE IF NOT EXISTS `leave_balance` (
`id_leave_balance` int(11) NOT NULL AUTO_INCREMENT,
`staff_id_staff` int(11) NOT NULL,
`leave_type_id_leave_type` int(11) NOT NULL,
`balance` int(3) NOT NULL,
`date_added` date NOT NULL,
PRIMARY KEY (`id_leave_balance`),
UNIQUE KEY `id_leave_balance_UNIQUE` (`id_leave_balance`),
KEY `fk_leave_balance_staff1` (`staff_id_staff`),
KEY `fk_leave_balance_leave_type1` (`leave_type_id_leave_type`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
------- Table leave ----------
CREATE TABLE IF NOT EXISTS `leave` (
`id_leave` int(11) NOT NULL AUTO_INCREMENT,
`staff_leave_application_id_staff_leave_application` int(11) NOT NULL,
`staff_leave_application_staff_id_staff` int(11) NOT NULL,
`leave_type_id_leave_type` int(11) NOT NULL,
`date` date NOT NULL,
`active` int(11) NOT NULL DEFAULT '1',
`date_updated` date NOT NULL,
PRIMARY KEY (`id_leave`,`staff_leave_application_id_staff_leave_application`,`staff_leave_application_staff_id_staff`),
KEY `fk_table1_leave_type1` (`leave_type_id_leave_type`),
KEY `fk_table1_staff_leave_application1` (`staff_leave_application_id_staff_leave_application`,`staff_leave_application_staff_id_staff`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=32 ;
Well, I still don't think you've provided enough information. It would be very helpful to have some sample data and your expected output (in tabular format). That said, I may have something you can start working with. This query finds all staff members, calculates their current leave (grouped by type), and determines the difference between that and their balance by leave type. Take a look at it, and more importantly (perhaps) the sqlfiddle here that I used which has the sample data in it (very important to determining if this is the correct path for your data).
SELECT
staff.id_staff,
staff.name,
COUNT(`leave`.id_leave) AS leave_count,
leave_balance.balance,
(COUNT(`leave`.id_leave) - leave_balance.balance) AS leave_difference,
`leave`.leave_type_id_leave_type AS leave_type
FROM
staff
JOIN `leave` ON staff.id_staff = `leave`.staff_leave_application_staff_id_staff
JOIN leave_balance ON
(
staff.id_staff = leave_balance.staff_id_staff
AND `leave`.leave_type_id_leave_type = leave_balance.leave_type_id_leave_type
)
WHERE
`leave`.active = 1
GROUP BY
staff.id_staff, leave_type;
Good luck!