MySQL query find matching column based on another column? - mysql

Sorry I don't know how to word the question's title.
I have a table like this
Prod Part Number
0001 101 3
0001 102 2
0001 103 1
0002 101 3
0002 102 2
0002 103 4
0003 101 2
0003 102 3
0003 103 6
0004 101 3
0004 102 2
0004 103 1
I want to find the product that has the correct number per part for all parts.
So something like
SELECT Prod from table
WHERE (Number of Part(101)) = 3
AND (Number of Part(102)) = 2
AND (Number of Part(103)) = 1
Output would be:
Prod
0001
0004
How can I achieve that?

You could use some inner join
select t1.Prod from
( select Prod
from my_table
where part = 101
and Number = 3 ) t1
inner join
( select Prod
from my_table
where part = 102
and Number = 2 ) t2 on t1.Prod = t2.Prod
inner join
( select Prod
from my_table
where part = 103
and Number = 1 ) t3 on t1.Prod = t3.Prod
http://sqlfiddle.com/#!9/014fe4/8

Through conditional aggregation:
SELECT Prod,
SUM(CASE WHEN Part = 101 AND Number = 3 OR
Part = 102 AND Number = 2 OR
Part = 103 AND Number = 1
THEN 1 ELSE 0 END) sum
FROM tbl
GROUP BY Prod
HAVING sum = 3
This will give you an extra column. If it's a problem then wrap everything into another SELECT.

Related

SQL LEFT JOIN 3 TABLES AND USING COUNT AND GROUP BY

I have 3 tables, users, branches and states
TABLE USERS
name code_branch
1 ANA 100
2 BEN 101
3 CARLA 102
4 DAN 100
5 ED 100
TABLE BRANCHES
code_branch branch_name code_state
1 100 BRANCH 100 A
2 101 BRANCH 101 A
3 102 BRANCH 102 C
4 103 BRANCH 103 D
5 104 BRANCH 104 E
6 105 BRANCH 105 F
TABLE STATES
code_state state_name
1 A STATE A
2 B STATE B
3 C STATE C
4 D STATE D
5 E STATE E
and i want the result as per below
state_name total_user
1 STATE A 4
2 STATE B 0
3 STATE C 1
4 STATE D 0
5 STATE E 0
My sql
SELECT s.code_state, COUNT(u.code_branch ) AS total
FROM ((states s
LEFT JOIN branches b ON s.code_state = b.code_state )
LEFT JOIN users u.code_branch = b.code_branch)
GROUP BY s.code_state;
and the result is
STATE TOTAL
A 4
B 0
C 1
D 0
E 0
I Want to show state_name instead of code_state in my query result above.
then i change on the first line like this
SELECT **s.state_name**, COUNT(u.code_branch ) AS total
and like this
SELECT **s.state_name, s.code_state** , COUNT(u.code_branch ) AS total
but get the error
Msg 8120, Level 16, State 1, Line 44
Column 's.state_name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Try adding the group by in the select statement?
SELECT **s.state_name, s.code_state** , COUNT(u.code_branch ) AS total
Group by **s.state_name, s.code_state**

Select record from table with not in other table

I am stuck in query I have a table like this
budget_details
id budget_id expenditure_head_id budget
1 1 1 1233
2 1 2 333
3 1 3 567
4 2 1 343
5 2 2 343
6 2 3 6767
7 2 4 557
expenditure_heads
id name
1 abc
2 xyz
3 qwe
4 uvw
I want to get all the expenditure_heads from budget_details that even
if not in budget_details like here budget_id=1 does not contain expenditure_head_id 4
but I want to select that to with 0 or null displaying
I tried this but it not displaying expenditure_head_id 4
select `expenditure_heads`.`name`, `budget_details`.`budget`, `budget_details`.`id` from
`budget_details`
right join `expenditure_heads` on `budget_details`.`expenditure_head_id` = `expenditure_heads`.`id`
where `budget_details`.`budget_id` = 1"
The where avoid you to get the missing row you need. The left join is done on the ON statement, so this query should work for you:
SELECT EH.name, BD.budget, BD.id FROM expenditure_heads EH
LEFT JOIN budget_details BD
ON (BD.expenditure_head_id = EH.id AND BD.budget_id = 1)

SQL: how to select a single id that meets multiple criteria from multiple rows

On a MySQL database, I have the table below
package_content :
id | package_id | content_number | content_name | content_quality
1 99 11 Yellow 1
2 99 22 Red 5
3 101 11 Yellow 5
4 101 33 Green 5
5 101 44 Black 5
6 120 11 Yellow 5
7 120 55 White 5
8 135 66 Pink 5
9 135 99 Orange 5
10 135 11 Yellow 5
and i am looking a possibility to make search queries on it:
I would like to select the package_id where content_number could be 11 AND 22 (In this case it should select only package_id 99
I really don't know if it's possible in SQL since the statement AND will always results as false. If i use the statement OR i also get the package_id 99, 101, 120, 135 and that's not what i want.
Maybe my table is not well designed too, but any suggestions would help!
Thanks in advance
Edit
I added the content_quality column
I used the sql query from juergen, works very well
select package_id
from package_content
where content_number in (11,22)
group by package_id
having count(distinct content_number) = 2
My last question is how could i now add another criteria : Select the package_id where content_number is 11 and 22 and content_number 11 has content_quality 1
Edit 2:
For the 2nd question i use now this query. Thanks to both of you who helped me! :)
SELECT *
FROM (
SELECT package_id
FROM package_content
WHERE
(content_number=11 AND content_quality > 1)
OR (content_number = 33 AND content_quality = 5)
OR (content_number = 44 AND content_quality =5 AND content_name like 'Black')
GROUP BY package_id
HAVING count( DISTINCT content_number) = 3
)t1
LEFT JOIN package_content ON package_content.package_id = t1.package_id
This will output
id | package_id | content_number | content_name | content_quality
3 101 11 Yellow 5
4 101 33 Green 5
5 101 44 Black 5
You need to group by the package_id and then use having to perform an aggregate function over the grouped data
select package_id
from package_content
where content_number = 22
or
(
content_number = 11 and content_quality = 1
)
group by package_id
having count(distinct content_number) = 2
You could query with a self join for that:
SELECT DISTINCT package_id
FROM package_content a, package_content b
WHERE a.package_id = b.package_id
AND a.content_number = 11 AND b.content_number = 22
Edit: For your second question: Just add that to the query. The package_content renamed to a is responsible for the content_number 11. Therefore you can ask, wether a has content_quality 1:
SELECT DISTINCT package_id
FROM package_content a, package_content b
WHERE a.package_id = b.package_id
AND a.content_number = 11 AND b.content_number = 22
AND a.content_quality = 1

Add total of 3 rows for specific id

I have three tables:
Students
-------------------------------------------------------------
studentId first last gender weight
-------------------------------------------------------------
1 John Doe m 185
2 John Doe2 m 130
3 John Doe3 m 250
Lifts
-------------------
liftId name
-------------------
1 Bench Press
2 Power Clean
3 Parallel Squat
4 Deadlift
5 Shoulder Press
StudentLifts
------------------------------------------------
studentLiftId studentId liftId weight
------------------------------------------------
1 1 1 185
2 2 3 130
3 3 1 190
4 1 2 120
5 2 1 155
6 3 2 145
7 1 1 135
8 1 1 205
9 2 3 200
10 1 3 150
11 2 2 110
12 3 3 250
I would like to have four top lists:
Bench Press
Parallel Squat
Power Clean
Total of the above 3
I can successfully grab a top list for each specific lift using the following query:
SELECT s.studentId, s.first, s.last, s.gender, s.weight, l.name, sl.weight
FROM Students s
LEFT JOIN (
SELECT *
FROM StudentLifts
ORDER BY weight DESC
) sl ON sl.studentId = s.studentId
LEFT JOIN Lifts l ON l.liftId = sl.liftId
WHERE l.name = 'Bench Press'
AND s.gender = 'm'
AND s.weight > 170
GROUP BY s.studentId
ORDER BY sl.weight DESC
However, I am stuck on how to add the highest total of each lift for each student. How can I first find the highest total for each student in each lift, and then add them up to get a total of all three lifts?
Edit
The result set that I am looking for would be something like:
-------------------------------------------------
studentId first last weight
-------------------------------------------------
3 John Doe3 585
1 John Doe 475
2 John Doe2 465
I also forgot to mention that I would actually like two lists, one for students above 170 and one for students below 170.
SELECT -- join student a total weight to the student table
A.studentId,
A.first,
A.last,
C.totalWeight
FROM
Student A,
(
SELECT -- for each studet add the max weights
sum(B.maxWeight) as totalWeight,
B.studentID
FROM (
SELECT -- for each (student,lift) select the max weight
max(weight) as maxWeight,
studentId,
liftID
FROM
StudentLifts
GROUP BY
studentId,
liftID
) B
GROUP BY
studentId
) C
WHERE
A.studentID = C.studentId
-- AND A.weight >= 170
-- AND A.weight < 170
-- pick one here to generate on of the two lists.

SELECTING with multiple WHERE range conditions on same column

I have tables like these:
A table B table
-------------------- -----------------------------------
item_ID | item_Name item_ID | option_ID | option_Value
-------------------- -----------------------------------
1 item_a 2 34 2000
2 item_b 2 45 3400
3 item_c 2 12 1200
4 item_d 3 34 500
5 item_e 3 13 500
6 item_f 4 45 700
I wrote a query to get items, for example which have option 34 = 2000 and option 12 = 1200 is:
SELECT A.item_ID, A.item_name
FROM A
LEFT JOIN B ON A.item_ID = B.item_ID
WHERE B.option_ID IN (34, 1200) AND
B.option_Value IN (1200, 2000) AND
GROUP BY A.item_ID
HAVING COUNT(A.item_ID) >= 2 /* count of option used for search, can be more*/
My problem is for some options I want to get range result , for example: where option id 34 is between 1000 and 2000 and option 12 is lower than 4000
Note : (option_id, option_value) pair is unique and i want to get items that match all of the conditions
How about this?
SELECT A.item_ID, A.item_name
FROM A
LEFT JOIN B ON A.item_ID = B.item_ID
WHERE (B.option_ID=34 AND B.option_value BETWEEN 1000 AND 2000)
OR (B.option_ID=12 AND B.option_value BETWEEN 0 AND 4000)
GROUP BY A.item_ID
HAVING COUNT(A.item_ID) >= 2
Maybe I didn't understand the question completely?
This should give you what you want:
WHERE
B.option_ID = 34 AND B.option_Value BETWEEN 1000 AND 2000
OR
B.option_ID = 12 AND B.option_Value < 4000
There might be a better way to do this if there was some rule according to which you want to filter... Otherwise, just use OR and AND to achieve what you want.