Using "OR" versus "AND" Operator for Getting Specific Results - sql-server-2008

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

Related

create a new column based on the conditions applied on the calculated average value in mysql, finally join the tables

I have two tables in mysql database
subjectids
id subject
11 Physics
12 Chemistry
13 Maths
14 Biology
15 History
16 Geography
studentsScores
id student subjectid score
1 Ahaan 11 45
2 Ahaan 12 33
3 Ahaan 13 49
4 Ivaan 11 41
5 Ivaan 12 38
6 Ivaan 13 46
7 Ann 11 40
8 Ann 12 30
9 Ann 13 50
I am trying to find the average of each subject and give a tag of easy , medium, hard based on the average value, like hard if avg<35, medium if avg between 35 and 45 and easy if avg greater than 45.
My expected result is
subject subjectid avg_score level
physics 11 42 medium
chemistry 12 33 hard
math 13 48 easy
I am new to sql, it would be great if you can help.
A simple JOIN and GROUP BY is enough to get your wanted result
SELECT `subject`, `subjectid`, ROUND(AVG(`score`),0) avg_score,
CASE
WHEN AVG(`score`) < 35 THEN 'hard'
WHEN AVG(`score`) between 35 and 45 then 'medium'
WHEN AVG(`score`) > 45 THEN 'easy'
end as level
FROM studentsScores ss JOIN subjectids si ON ss.`subjectid` = si.`id`
GROUP BY `subject`,`subjectid`
subject
subjectid
avg_score
level
Physics
11
42
medium
Chemistry
12
34
hard
Maths
13
48
easy
fiddle
A simple case statement would do the trick.
select si.subject,
si.id,
AVG(ss.score) as avg_score,
case when AVG(ss.score) < 35 then 'hard'
when AVG(ss.score) between 35 and 45 then 'medium'
when AVG(ss.score) > 45 then 'easy'
end as level
from subjectids si
inner join studentsScores ss on si.id=ss.subjectid
group by si.subject,si.id ;
https://dbfiddle.uk/IDS43R9W

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.

MySQL seems to ignore my WHERE clause with inner joins

In order to display data (orders or bids) in a excel-like grid, i fetch from my database with the help of this query. In this case, the order_bid table store the lines that compose an order (a line for each item), the item table defines the price of an item, the current sale the item is displayed on, and the lot table defines the item itself (name, description_ect...)
Here is the request i make, orders are another table but the important part is that an order_bid is linked to an order, and orders are linked to a unique sale, but it seems to ignore the WHERE close, so i get a lot more results than expected (for example if a client placed a bid for lot 4 of sale 1, i would see a bid for sale 2 lot 4, and so on for all sales that have a lot number 4 (so all of them basically))
SELECT o.id, o.order_id, o.lot_num, o.bid, i.lot_id, i.sale, i.price, l.description_fr
FROM order_bid o
INNER JOIN item i
ON o.lot_num = i.lot_num
INNER JOIN lot l
ON l.id = i.lot_id
WHERE o.order_id = 38
For example i expect for a request a result like:
id
order_id
lot_num
bid
lot_id
sale
price
description_fr
110
38
17
135
19
sale1
135
description1
111
38
21
83
23
sale1
183
description2
109
38
10
100
790
sale1
100
description3
but i get:
id
order_id
lot_num
bid
lot_id
sale
price
description_fr
110
38
17
135
19
sale1
135
description1
111
38
21
83
23
sale1
183
description2
111
38
21
183
11968
sale11
150
description4
109
38
10
100
790
sale1
100
description3
and a lot of other lots that i shouldn't be getting from other sales
and i verified, when i request all the order_bid with order_id = 38 (SELECT * FROM order_bid WHERE order_id = 38) i get:
id
order_id
lot_num
bid
109
38
10
100
110
38
17
135
111
38
21
183
summarized: i get info from multiple sales when i'm supposed to get only from one (done using the order_id filter)

mysql several column ranking per group

I have table data in this format
studno name level year term subject1 subject2 subject3
212 victor l1 2000 1 45 56 80
213 HOM l1 2000 1 42 56 70
214 ken l1 2000 1 60 70 50
215 ted l1 2000 1 46 36 47
212 victor l1 2000 2 45 36 68
213 Hom l1 2000 2 38 78 49
214 ken l1 2000 2 38 34 62
my desired output is the following
studno name level year term subject1 sub1rank subject2 sub2rank
213 victor l1 2000 1 42 3 56 2
214 HOM l1 2000 1 60 1 70 1
215 TED l1 2000 1 46 2 36 3
212 victor l1 2000 2 45 2 36 1
213 hOM l1 2000 2 38 3 36 1
214 KEN l1 2000 2 38 3 32 3
215 TED l1 2000 2 90 1 30 4
I have managed to get the rank but the problem is how to get the rank per year, level, term and subject. another problem is that if i use nested statement and try to create view in mysql database it throws an error, "View's SELECT contains a subquery in the FROM clause"
You can do this with correlated subqueries in the select clause. If I understand correctly, something like this:
select t.*,
(select COUNT(distinct t1.subject1)
from t t2
where t2.level = t.level and t2.year = t.year and t2.term = t.term and
t2.subject1 >= t.subject1
) as subj1rank,
(select COUNT(distinct t2.subject2)
from t t2
where t2.level = t.level and t2.year = t.year and t2.term = t.term and
t2.subject2 >= t.subject2
) as subj2rank
from t
The count(*) might be count(distinct subject1) (etc.), depending on how you treat ties.

Using mySQL to compare 2 tables

I'm trying to compare 2 mySQL tables to find differences between them. A record may be found in TableA but not in TableB, or vice versa.
My tables are as follows:
TableA
Name A1 A2 B1 B2
------------------------
John 11 12 21 23
John 11 12 21 22
John 33 34 31 33
Mary 41 42 54 55
Mary 71 72 81 82
Mary 41 42 51 52
TableB
Name A1 A2 B1 B2 C D
---------------------------------
John 11 12 21 22 999 999
John 21 23 11 12 999 999
John 31 32 33 34 999 999
Mary 41 42 51 52 999 999
Mary 54 55 41 42 999 999
Columns A1 and A2 is considered a group, and B1 and B2 considered another group. For a record to be considered found in both tables, I need
- TableA(A1,A2) = TableB(A1,A2) AND TableA(B1,B2) = TableB(B1,B2)
OR
- TableA(A1,A2) = TableB(B1,B2) AND TableA(B1,B2) = TableB(A1,A2)
For the 2 tables, above, I would compare all of TableA's John to all of TableB's John, and all of TableA's Mary to all of TableB's Mary.
I should get the output
Name A1 A2 B1 B2 C D
-----------------------------------------------
John 31 32 33 34 999 999 (from TableB)
Mary 41 42 54 55 (from TableA)
Mary 71 72 81 82 (from TableA)
Mary 54 55 41 42 999 999 (from TableB)
I'm new to mySQL, and the above seems so complicated to me that I'm not even sure where to start.
I would really appreciate any help on this.
If I understood you correctly, you need to issue two queries: one for finding records from TableA not existing in TableB, and second one for the opposite situation. Note that in one case it's LEFT JOIN and in the second case it's RIGHT JOIN.
SELECT a.*, '' AS C, '' AS D, '(from TableA)' AS 'table'
FROM TableA AS a
LEFT JOIN TableB AS b
ON ((a.A1 = b.A1 AND a.A2 = b.A2 AND a.B1 = b.B1 AND a.B2 = b.B2)
OR (a.A1 = b.B1 AND a.A2 = b.B2 AND a.B1 = b.A1 AND a.B2 = b.A2))
AND a.Name = b.Name
WHERE b.Name IS NULL
UNION
SELECT b.*, '(from TableB)' AS 'table'
FROM TableA AS a
RIGHT JOIN TableB AS b
ON ((a.A1 = b.A1 AND a.A2 = b.A2 AND a.B1 = b.B1 AND a.B2 = b.B2)
OR (a.A1 = b.B1 AND a.A2 = b.B2 AND a.B1 = b.A1 AND a.B2 = b.A2))
AND a.Name = b.Name
WHERE a.Name IS NULL