SELECT t1.s_name, count(*) FROM tvSeries AS t1, subTitles AS t2, votes as t3
WHERE
t1.s_id IN (SELECT t2.s_id WHERE sLang='English') AND
t1.s_id IN (SELECT t3.s_id WHERE pts=5) AND
t1.s_id IN (SELECT t3.s_id WHERE uid='britney');
My tvSeries table is like:
s_id s_cat s_name
1 comedy a
2 comedy b
3 drama c
4 comedy d
5 drama e
My subTitles table is like:
s_id sLang
1 English
1 Spanish
2 French
2 English
3 English
1 French
4 German
4 English
5 English
My votes table is like:
s_id uid pts
1 john 4
1 mia 3
1 britney 5
2 rock 5
3 anna 1
3 britney 5
4 megan 3
5 britney 5
I want to select total number of tvSeries and name of tvSeries in this conditions;
which tvSeries gets 5 star from user 'britney' with English subtitles.
When I use my code, I get only one row with number of tvSeries but i want to see many rows with total value. Can anyone help me?
You can do this with simple JOINs (see this answer for an explanation of JOIN vs ,), and then your conditionals are clean and easy to understand.
SELECT
t.s_id,
t.s_name
FROM
tvSeries t
JOIN subTitles s ON s.s_id = t.s_id
JOIN votes v ON v.s_id = t.s_id
WHERE
s.sLang = 'English'
AND v.pts = 5
AND v.uid = 'britney';
If you want just the count of shows instead, you can do:
SELECT
COUNT(*) as count
FROM
...
You can't easily get both the names of the series as well as the count in the same row (because COUNT is an aggregating function), but if you need it you can do:
SELECT
GROUP_CONCAT(t.s_name) as series_names,
COUNT(*) as count
FROM
...
though that returns a single row with concatenated series names (a,c,e) rather than rows which are able to be iterated over.
See http://sqlfiddle.com/#!9/2c252c/13 for a working example.
Related
I'm defining the relationship between the two tables using a join table. I want to arrange them in the order of many overlapping things. Currently, we are using subquery, is there a way to get the same result using join?
People FoodTable PeopleFood
ID | NAME ID | Food ID | PeopleId | FoodId
1 BOB 1 Hamberger 1 1 1
2 JOHN 2 Pizza 2 1 2
3 KATY 3 Chicken 3 1 3
4 MILLER 4 Salad 4 2 1
5 AMANDA 5 Sushi 5 2 2
6 2 3
7 3 2
8 3 3
9 4 3
10 4 5
11 5 5
When the table is defined in this way, I want to arrange food tastes similar to Bob's.
I'm doing it like this now.
SELECT people_id, COUNT(people_id) as count
FROM peopleFood
WHERE food_id IN
(SELECT food_id FROM peopleFood
WHERE people_id = 1)
AND people_id != 1
GROUP BY people_id
ORDER BY count DESC;
-- Result -------------
People_id | count
2 3
3 2
4 1
Is there a better way to change this method or use join?
Thank you!!!
You have been inconsistent in your use of the table and column names -
Tables - PeopleFood in your sample data but you reference peopleFood in your query.
Columns - PeopleId and FoodId in your sample data but you reference people_id and food_id in your query.
Choose a naming convention and stick to it. Everyone has there own preference but the important thing is to be consistent.
The equivalent query with INNER JOIN instead of your sub-query is -
SELECT
`pf2`.`people_id`,
COUNT(`pf2`.`food_id`) as `count`
FROM `PeopleFood` `pf1`
INNER JOIN `PeopleFood` `pf2`
ON `pf2`.`people_id` <> `pf1`.`people_id`
AND `pf2`.`food_id` = `pf1`.`food_id`
WHERE `pf1`.`people_id` = 1
GROUP BY `pf2`.`people_id`
ORDER BY `count` DESC;
The performance difference between the two queries is unlikely to be noticeable and it might be argued that the intent is clearer in your version with the sub-query.
The surrogate key ID on your PeopleFood table should be dropped in favour of the compound “natural” primary key on people_id and food_id.
The Cost of Useless Surrogate Keys in Relationship Tables
Inner join:
SELECT p.People_id, COUNT(p.People_id) as count FROM PeopleTable p
INNER JOIN FoodTable f
ON(p.People_id = f.FoodId)
WHERE people = 1
GROUP BY p.people_id
ORDER BY count DESC;
If it helps, please mark it as an accepted answer!
I'm a bit stuck on this question and was hoping for some help. Here's where I'm at currently.
I have this TEST table of Names. Each Person can either be a recruiter or an employee. The number in Recruited_by is associated with the person_id.
Person_id Name Recruited_by
1 Jean Grayson 1
2 Paul Smith 7
3 John Do Null
4 Alex Lee 7
5 Lisa Kim 7
6 Bob Thompson 3
7 Mike Keen Null
8 Raymond Red 3
9 Alisson Jones 1
10 Kate James 3
Here is the query I have so far which I'm trying to the names of the recruiters that hire more than 3 employees (which will return nothing in this case) and the number of employees that were NOT recruited by anyone (which would be the NULL names).
SELECT T.Name as Employees, COUNT(T1.Name) as Not_hired
FROM Test AS T
WHERE COUNT(T1.Name) IS NULL
LEFT OUTER JOIN Test AS T1
ON T.Recruited_by = T1.Person_id
GROUP BY T.Name
HAVING COUNT(T1.Name) > 3
However this query is returning nothing when I should expect it to return the number of employees who were not hired by a recruiter!
If you want in the results only 1 row with 2 columns then you can do a LEFT join of the table to a query that aggregates to get the ids of the persons that hired more than 3 persons and aggregate again to get the number of persons that were not recruited by anyone:
SELECT GROUP_CONCAT(CASE WHEN t2.Recruited_by IS NOT NULL THEN t1.Name END ORDER BY t1.Name) names,
SUM(t1.Recruited_by IS NULL) total_not_recruited
FROM Test t1
LEFT JOIN (
SELECT Recruited_by
FROM Test
GROUP BY Recruited_by
HAVING COUNT(*) > 3
) t2 ON t2.Recruited_by = t1.Person_id;
You will get the names of the persons that hired more than 3 persons (if they exist) as a comma separated list.
See the demo.
I have four tables detailing an amusement park and its guests' ride history.
Categories
c_id name
1 Thrill
2 Leisure
3 Kiddie
Rides
r_id c_id
1 1
2 1
3 2
4 2
5 3
6 3
guest_history
h_id g_id
1 1
2 1
3 2
4 3
history_items
h_id r_id
1 5
2 6
3 1
3 2
4 5
How would I get all of the guests (g_id's) that have either rode all of the kiddie rides or none of the kiddie rides?
Expected Output would be:
g_id
1
2
I can't seem to figure out what the easiest way to go about it would be. I can only seem to conjure up a table that contains all of the cases that a guest has rode a kiddie ride. My attempt was a 4-way inner join of the tables and to filter out on the c_id = "Kiddie". Any help would be appreciated.
You can try this below logic-
3 is fixed in the query to get category "Kiddie"
DEMO HERE
SELECT A.g_id,COUNT(C.r_id)
FROM guest_history A
INNER JOIN history_items B ON A.h_id = B.h_id
INNER JOIN Rides C ON B.r_id = C.r_id AND C.c_id = 3
GROUP BY A.g_id
HAVING COUNT(DISTINCT B.r_id) = (SELECT COUNT(r_id) FROM Rides WHERE c_id = 3)
OR COUNT(DISTINCT B.r_id) = 0
SELECT g_id
FROM Categories
NATURAL JOIN Rides
NATURAL JOIN guest_history
NATURAL JOIN history_items
GROUP BY g_id
HAVING COUNT(DISTINCT r_id) IN (0,
(SELECT COUNT(DISTINCT r_id)
FROM Categories
NATURAL JOIN Rides
WHERE name = 'Kiddie')
)
fiddle
Say I have three tables:
TABLE A
idA variable
1 Number of hats
2 Number of scarves
3 Number of mittens
TABLE B
idB name
1 Andy
2 Betty
3 Cedric
4 Daphne
TABLE C
idA idB value
1 1 15
1 2 2
1 3 89
2 1 10
2 3 3
2 4 1504
3 2 12
3 3 4
3 4 1
Looking at the table, it's relatively simple to work out - we know how many hats (2) and mittens (12) that she owns, but not how many scarves. Likewise, for Daphne we know how many scarves (1504) and mittens (1) she owns, but not the amount of hats.
However, I'd like a list of fields that there ISN'T information for - I would have a returned result looking something like this (if I asked for Andy)
idA variable
3 Number of mittens
Any idea how I do that? :)
The following query works:
SELECT B.name, A.variable
FROM B
CROSS JOIN A
LEFT JOIN C ON C.idA = A.idA AND C.idB = B.idB
WHERE C.value IS NULL
Its the CROSS JOIN that is key, it says JOIN every record in B to every record in A. Once you've done that you can easily check which combinations of idA and idB don't have a corresponding record in C.
Tested on SQLFiddle
Result:
NAME UNKNOWN VARIABLE
-------------------------------
Andy Number of mittens
Betty Number of scarves
Daphne Number of hats
You can use joins to associate 2 tables.
In your case, if you ask for Andy and you wanna know the number of mittens, you'll have:
SELECT name, value
FROM B
INNER JOIN C on B.idB = C.idB
WHERE id.A = 3
Responding to your comment, you try something like that:
SELECT name, variable
FROM B
RIGHT JOIN C on B.idB = C.idB
RIGHT JOIN A on C.idA = A.idA
WHERE C.idA IS NULL
select idA, variable
from a
where idA not in (select idA from c where idB = 1)
Hello i've a table similar to this one:
id sponsor name
------------------------
1 0 Sasha
2 1 John
3 1 Walter
4 3 Ashley
5 1 Mark
6 4 Alexa
7 3 Robert
8 3 Frank
9 4 Marika
10 5 Philip
11 9 Elizabeth
when i choose an ID (call it MYCHOICE) i want know all the name of people who has sponsor like MYCHOICE... is simply:
select * from tablename where sponsor=MYCHOICE
but... here is the problem... i would know how many people there is in the downline of this results... so... how many records there are with sponsor like each id.
if i choose id 1 result should be
id name downline
----------------------
2 John 0 (noone with sponsor=2)
3 Walter 3 (3 with sponsor=3: ashley, robert, frank)
5 Mark 1 (1 with sponsor=5: philip)
if i choose id 4 result should be
id name downline
----------------------
6 Alexa 0
9 Marika 1 (1 with sponsor=9: Elizabeth)
i try this "bad solution" if mychoice is 1
select sponsor,count(*) as downline from tablename where sponsor in
(select id from tablename where sponsor=1) group by sponsor order by
downline desc
result of this query is
sponsor downline
---------------------
3 3
5 1
there are 2 problems:
- names are not rights and is not that i want
- the count 0 "2|John|0" in the example dont appears
thank u for advice and help, sorry for english,
N.
SELECT child.id,
child.name,
COUNT(grandchild.sponsor) downline
FROM TableName child
INNER JOIN TableName parent
ON child.sponsor = parent.id AND
parent.id = ? -- << user choice
LEFT JOIN TableName grandchild
ON child.id = grandchild.sponsor
GROUP BY child.id, child.name
SQLFiddle Demo
As you can see, the table is joined to itself twice. The first join that uses INNER JOIN gets the records associated with the Sponsor which is your user_choice. The second join which uses LEFT JOIN gets all the records associated with records from your user_choice.