Counting Number of Males/females within a blood group - mysql

So I have two Data Tables 'DONOR' AND 'ACCEPTOR'. Each have the following schema:
DID|NAME|GENDER|CITY|BG |AMOUNT
INT|STR |CHAR |STR |STR|INT
I'm trying to create a query to output the Gender and Blood Group (BG) as well as a Count for that Gender+Blood Group to do this I created the following query which is kind of correct but I only want it to output each Gender+Blood Group once with the total count which i don't exactly understand how to do (I'm learning SQL and I figured out how to get this query and union it but not make it so each Gender + Blood Group only outputs once)
My Query:
SELECT DISTINCT GENDER,BG,COUNT(BG) COUNTVALUE FROM DONOR GROUP BY GENDER,BG
UNION ALL
SELECT DISTINCT GENDER,BG,COUNT(BG) COUNTVALUE FROM ACCEPTOR GROUP BY GENDER,BG
Example Output:
F A+ 30
F AB+ 75
M A- 47
M AB+ 36
M 0+ 53
. . .
My Output:
F A+ 69
F A- 49
F AB+ 62
F AB- 61
F B+ 67
F B- 63
F O+ 45
F O- 59
M A+ 55
M A- 71
M AB+ 76
M AB- 63
M B+ 59
M B- 68
M O+ 67
M O- 66
F A+ 51
F A- 57
F AB+ 71
F AB- 62
F B+ 60
F B- 70
F O+ 52
F O- 69
M A+ 70
M A- 60
M AB+ 71
M AB- 68
M B+ 66
M B- 53
M O+ 52
M O- 68

To get what you want, you will have to use a subquery:
SELECT t.GENDER, t.BG, SUM(t.COUNTVALUE) TOTAL
FROM (
SELECT GENDER,BG,COUNT(BG) COUNTVALUE FROM DONOR GROUP BY GENDER,BG
UNION ALL
SELECT GENDER,BG,COUNT(BG) COUNTVALUE FROM ACCEPTOR GROUP BY GENDER,BG
) AS t
GROUP BY t.GENDER, t.BG
Note I removed DISTINCT because it was superfluous. The GROUP BY is already sure to return only one row per distinct GENDER, BG pair in each query.

Related

mysql - select MAX value by a group return wrong values of other column

I want to find MAX value by the code and my data like below:
id
date
code
price
74
2022-01-04
B
64
91
2022-01-07
A
174
112
2022-01-11
B
128
245
2022-01-12
C
841
550
2022-01-14
A
79
780
2022-01-20
B
55
821
2022-01-23
D
45
868
2022-01-28
C
50
890
2022-02-02
B
467
891
2022-02-03
D
58
892
2022-02-04
A
472
What I expect, it will return like below:
id
date
code
price
245
2022-01-12
C
841
890
2022-02-02
B
467
891
2022-02-03
D
58
892
2022-02-04
A
472
I'm using below query:
select x.id, x.date, x.code, y.yprice
from data AS x
inner join
(
select id, date, code, MAX(price) AS yprice
from data
group by code
) y
on x.id = y.id AND x.code = y.code
and give me below result:
About the result:
The value of MAX is right, however the id and date is wrong.
Any idea to fix the query?
Thank You...
SELECT X.ID,X.DATE,X.CODE,X.PRICE
FROM
(
SELECT C.id,C.date,C.code,C.price,
ROW_NUMBER()OVER(PARTITION BY C.code ORDER BY C.Price DESC)XCOL
FROM test AS C
)X WHERE X.XCOL=1
Could you please try this one

Calculate the number of users based on the below conditions by writing a single query SQL

There are two campaigns running campaign A and Campaign B and list of user ids participated in those two campaign is given below. Calculate the number of users based on the below conditions by writing a single query.
Participated in campaign A
Participated in campaign B
Participated in campaign A only
Participated in campaign B only
Participated in both the campaigns
Participated in either campaign A or Campaign B
Campaign A Campaign B
user_id user_id
91 62
27 11
58 16
50 92
64 17
65 71
54 12
98 37
78 93
24 58
31 54
73 94
63 85
72 30
94 32
20 1
38 48
8 99
43 45
33 46
26 39
100 29
61 49
87 73
84 81
15 88
80 70
77 33
40 55
82
42
56
95
88
I am not able to figure out how to write in single SQL query.
Assuming you have two different tables, you can use union all and aggregation:
select in_a, in_b, count(*) as num_users
from ((select user_id, 1 as in_a, 0 as in_b
from a
) union all
(select user_id, 0 as in_a, 1 as in_b
from b
)
) u
group by in_a, in_b;
This gives you all the information you need. You can use group by in_a, in_b with rollup to get all combinations.
Or, you can summarize this into one row:
select sum(in_a) as in_a, sum(in_b) as in_b,
sum(in_a * (1 - in_b)) as in_a_only,
sum(in_b * (1 - in_a)) as in_b_only,
sum(in_a * in_b) as in_ab
from ((select user_id, 1 as in_a, 0 as in_b
from a
) union all
(select user_id, 0 as in_a, 1 as in_b
from b
)
) u;
Note: These both assume that users are unique in each campaign. If not, just use select distinct or union in the subquery.

How to reference on a different row when you have a joint key in MySQL workbench?

my code in MySQL workbench
SELECT
id,
user_id,
parent_id,
approved_time,
#new_approved_t:=IF(new_product_type != 'B', approved_time, #new_approved_t))AS new_approved_time
FROM p
my data frame look like this after I run the code:
id user_id parent_id product_type approved_time New_approved_time
30 11 NA A 8/4/2017 8/4/2017
31 11 30 B 12/1/2017 8/4/2017
54 5 NA A 5/5/2018 5/5/2018
322 5 54 B 7/22/2018 5/5/2018
21 5 NA C 8/1/2018 8/1/2018
13 5 NA C 8/2/2018 8/2/2018
2445 5 NA C 9/25/2018 9/25/2018
111 44 NA A 10/4/2018 10/4/2018
287 44 111 B 10/8/2018 10/4/2018
211 33 NA A 12/5/2018 12/5/2018
277 33 211 B 12/25/2018 12/5/2018
1120 33 NA C 1/1/2019 1/1/2019
1389 33 211 B 1/11/2019 1/1/2019
I would like all my product_type ending in 'B' and it's new_approved_time column to use the corresponding parent_id approved time. The result should look like in below:
id user_id parent_id product_type approved_time New_approved_time
30 11 NA A 8/4/2017 8/4/2017
31 11 30 B 12/1/2017 8/4/2017
54 5 NA A 5/5/2018 5/5/2018
322 5 54 B 7/22/2018 5/5/2018
21 5 NA C 8/1/2018 8/1/2018
13 5 NA C 8/2/2018 8/2/2018
2445 5 NA C 9/25/2018 9/25/2018
111 44 NA A 10/4/2018 10/4/2018
287 44 111 B 10/8/2018 10/4/2018
211 33 NA A 12/5/2018 12/5/2018
277 33 211 B 12/25/2018 12/5/2018
1120 33 NA C 1/1/2019 1/1/2019
1389 33 211 B 1/11/2019 12/5/2018 <-this is where I dont know how to write my code
Thank you!
Found a solution here with another column I didn't include in my example, but basically it's the reverse of parent_id column I listed above which only listed id in product_type A and rest of them is null.
But I got hint from Dan's code on COALESCE() function, thanks Dan.
CASE WHEN c.new_product_type IN ('A', 'B') THEN #new_approved_t:=IF(COALESCE(if((a.is_loc=1 AND b.ploc_RID IS NOT NULL), a.id, null)), a.approved_time, #new_approved_t)
ELSE a.approved_time END AS new_approved_time
Because the parent (pp) has its own value there needs to be a self join like this. Because of the join criteria pp.approved_time will be NULL for non-B products.
SELECT
p.id,
p.user_id,
p.parent_id,
p.approved_time,
COALESCE(pp.approved_time, p.approved_time) AS new_approved_time
FROM p
LEFT JOIN p AS pp ON p.new_product_type = 'B' AND p.parent_id = pp.id

sum field with GROUP BY fails

I have a very nasty query. I try to get a classification table sorted by touchdowns... But before reaching that goal I have a problem with a sum... let me explain.
With this query:
SELECT tft.id_team
, z.id_partido
, y.td
FROM `team_faseTorneo` tft
LEFT
JOIN
( SELECT j.id_fase
, tp.id_team
, tp.id_partido
FROM jornadas j
LEFT
JOIN partidos USING(id_jornada)
JOIN team_partido tp USING(id_partido)
) z
ON z.id_fase = tft.id_fase
AND z.id_team=tft.id_team
LEFT
JOIN
( SELECT p.id_team
, pL.id_partido
, pL.td
FROM players p
JOIN playerLogros pL USING(id_player)
) y
ON y.id_team = tft.id_team
AND y.id_partido = z.id_partido
WHERE tft.id_fase = 4
The result is this one:
id_team id_partido td
6 69 0
6 69 0
6 69 0
6 69 0
6 81 0
6 81 0
6 81 0
6 81 1
6 84 1
6 84 0
6 98 NULL
6 99 NULL
6 114 NULL
6 116 NULL
6 129 NULL
6 133 NULL
6 144 NULL
6 150 NULL
6 159 NULL
6 167 NULL
19 72 0
19 72 0
19 77 2
19 77 0
19 77 1
19 77 0
19 77 0
19 89 0
19 89 0
19 92 NULL
NUll is for the matchs(partidos) not played yet. I need to sum all the touchdowns scored by match (partido), so I tried this:
SELECT tft.id_team,z.id_partido, y.td FROM `team_faseTorneo` tft
LEFT JOIN (SELECT j.id_fase, tp.id_team, tp.id_partido FROM jornadas j LEFT JOIN partidos USING(id_jornada) JOIN team_partido tp USING(id_partido)
) z ON(z.id_fase=tft.id_fase AND z.id_team=tft.id_team) LEFT JOIN(SELECT p.id_team, pL.id_partido, SUM(pL.td) td FROM players p JOIN playerLogros pL USING(id_player) GROUP BY p.id_team) y ON(y.id_team=tft.id_team AND y.id_partido=z.id_partido)
WHERE tft.id_fase=4
But the result is this:
id_team id_partido td
6 69 NULL
6 81 NULL
6 84 NULL
6 98 NULL
6 99 NULL
6 114 NULL
6 116 NULL
6 129 NULL
6 133 NULL
6 144 NULL
6 150 NULL
6 159 NULL
6 167 NULL
19 72 3
19 77 NULL
19 89 NULL
19 92 NULL
19 106 NULL
How Can I solve this?
Thanks in advance!! :)
If you need a sum, then use an aggregation query. Perhaps something like this:
SELECT tft.id_team, z.id_partido, SUM(y.td)
FROM `team_faseTorneo` tft LEFT JOIN
(SELECT j.id_fase, tp.id_team, tp.id_partido
FROM jornadas j LEFT JOIN
partidos
USING (id_jornada) JOIN
team_partido tp
USING (id_partido)
) z
ON z.id_fase=tft.id_fase AND z.id_team=tft.id_team LEFT JOIN
(SELECT p.id_team, pL.id_partido, pL.td td
FROM players p JOIN
playerLogros pL
USING (id_player)
) y
ON y.id_team=tft.id_team AND y.id_partido=z.id_partido
WHERE tft.id_fase = 4
GROUP BY tft.id_team, z.id_partido;
Your query seems overly complicated, but this should at least get you the sum of td.
I think that I got it...
SELECT tft.id_team,z.id_partido, sum(z.td) FROM `team_faseTorneo` tft
LEFT JOIN (SELECT j.id_fase, tp.id_team, tp.id_partido, y.td FROM jornadas j LEFT JOIN partidos p USING(id_jornada) JOIN team_partido tp USING(id_partido) LEFT JOIN(SELECT p.id_team, pL.id_partido, (pL.td) td FROM players p JOIN playerLogros pL USING(id_player) ) y ON(y.id_team=tp.id_team AND y.id_partido=tp.id_partido) WHERE p.status='Finalizado'
) z ON(z.id_fase=tft.id_fase AND z.id_team=tft.id_team)
WHERE tft.id_fase=4 GROUP BY tft.id_team, z.id_partido ORDER BY tft.id_team

Using "OR" versus "AND" Operator for Getting Specific Results

Will do my best to explain my problem here. I ran a query which works good for checking people who have completed either courseIDNum=11 or courseIDNum=12 in districtIDNum=5, but NOT both courseIDNums. Here is the script:
SELECT max(p.FirstName),
max(p.LastName),
max(p.Email),
max(s.CourseIDNum)
FROM People p
INNER JOIN Registration r
on p.PeopleID = r.PeopleIdNum
INNER JOIN Section s
on r.SectionIDNum = s.SectionID
INNER JOIN School sc
on p.SchoolIDNum = sc.SchoolID
WHERE s.CourseIDNum IN (11, 12)
AND sc.DistrictIDNum = 5
AND r.Completed='Y'
group by p.PeopleID
having count(distinct s.CourseIDNum)=1
Now I am tasked to retrieve data for the people in districtIDNum=5 again, but this time to check if they have taken all 3 courses, which 2 out of the 3 courses have the same course name but each of these 2 courses has 2 different courseIDNums. So, I edited the WHERE portion shown below. The results returned are only people who completed 12 and 177, there is no result for 11, 68 and 128. Then, I replaced the OR with the AND operator, and 0 rows is returned. Any help in this is much appreciated!
WHERE s.CourseIDNum IN (11, 12)
OR s.CourseIDNum IN (68, 177)
OR s.CourseIDNum=128
AND sc.DistrictIDNum = 5
AND r.Completed='Y'
group by p.PeopleID
having count(distinct s.CourseIDNum)=3
Here are the tables involved:
peopleID FirstName LastName Email schoolIDNum
1 Esther B b#hotmail.com 33
2 Tommy L l#hotmail.com 55
3 Liz M m#hotmail.com 90
registrationID peopleIDNum sectionIDNum
22 1 40
23 2 41
24 3 132
25 1 78
26 2 52
27 1 63
sectionID courseIDNum
40 11
41 12
52 68
63 128
78 177
132 195
courseID coursename
11 Health (Old)
12 Health (New)
68 PE (Old)
128 Keyboarding
177 PE (New)
195 Computing
schoolID districtIDNum
33 5
55 5
90 12