I can't get around INNER JOIN in MySQL - mysql

I have two tables in my database. One of which is a table called players and the other one is bans:
players table: ID, Score
bans table: user_id, reason
What I need to do is: select players that where reason = cheating and Score < 250.
I tried doing some JOINS when I tried FULL JOIN I found that thing doesn't exist in MySQL so any help would be good, thanks in advance!
I also tried it like this but I always get zero rows
SELECT bans.user_id, players.ID
FROM bans
INNER JOIN players ON bans.user_id=players.ID;
BANS TABLE
user_id reason
133032 swearing
133040 name not allowed
PLAYERS TABLE
id score
15 13378
21 215216
133032 15
133040 157

You query is a good start. For your sample data, it will give you results. To meet your requirement, you just need a few additional filters:
select b.user_id, p.id
from bans b
inner join players p
on p.id = b.user_id
and p.score < 250
where b.reason = 'cheating'

Related

How do add data to multiple columns at the same time

I got this last task before I can go to bed...
Make a query that shows the name(not the id) of players who have won the lottery more than once, how many times they've won and the name(not the id) of the municipality they live in.
Players-table: PlayerNum, Name, Address, MunicipalityID
Winners-table: PlayerNum, DrawID
Municipality-table: MunicipalityID, County, Population, Name
Thank you sooo much in advance!!
You need to join the tables and do a sub query on the winner table using count and group by the join the result set with player
Not sure what the draw table does
You really should make an attempt instead of just asking for the solution.
Your starting point is to find the users who have won more than once. This is a simple GROUP BY of PlayerNum and the HAVING clause to limit the result based on the COUNT -
SELECT PlayerNum, COUNT(DrawID) AS num_wins
FROM Winners
GROUP BY PlayerNum
HAVING num_wins > 1
The next step is to add the names of the players. For this you need to join to the Players table and I have added table aliases (w & p) to avoid retyping the full table name each time -
SELECT p.Name, COUNT(DrawID) AS num_wins
FROM Winners w
INNER JOIN Players p
ON w.PlayerNum = p.PlayerNum
GROUP BY w.PlayerNum
HAVING num_wins > 1
And then finally the join to Municipality to get the Name with a column alias as we already have a Name column -
SELECT p.Name, COUNT(DrawID) AS num_wins, m.Name AS MunName
FROM Winners w
INNER JOIN Players p
ON w.PlayerNum = p.PlayerNum
INNER JOIN Municipality m
ON p.MunicipalityID = m.MunicipalityID
GROUP BY w.PlayerNum
HAVING num_wins > 1

MySQL View in place of subquery does not return the same result

The query below is grabbing some information about a category of toys and showing the most recent sale price for three levels of condition (e.g., Brand New, Used, Refurbished). The price for each sale is almost always different. One other thing - the sales table row id's are not necessarily in chronological order, e.g., a toy with a sale id of 5 could have happened later than a toy with a sale id of 10).
This query works but is not performant. It runs in a manageable amount of time, usually about 1s. However, I need to add yet another left join to include some more data, which causes the query time to balloon up to about 9s, no bueno.
Here is the working but nonperformant query:
SELECT b.brand_name, t.toy_id, t.toy_name, t.toy_number, tt.toy_type_name, cp.catalog_product_id, s.date_sold, s.condition_id, s.sold_price FROM brands AS b
LEFT JOIN toys AS t ON t.brand_id = b.brand_id
JOIN toy_types AS tt ON t.toy_type_id = tt.toy_type_id
LEFT JOIN catalog_products AS cp ON cp.toy_id = t.toy_id
LEFT JOIN toy_category AS tc ON tc.toy_category_id = t.toy_category_id
LEFT JOIN (
SELECT date_sold, sold_price, catalog_product_id, condition_id
FROM sales
WHERE invalid = 0 AND condition_id <= 3
ORDER BY date_sold DESC
) AS s ON s.catalog_product_id = cp.catalog_product_id
WHERE tc.toy_category_id = 1
GROUP BY t.toy_id, s.condition_id
ORDER BY t.toy_id ASC, s.condition_id ASC
But like I said it's slow. The sales table has about 200k rows.
What I tried to do was create the subquery as a view, e.g.,
CREATE VIEW sales_view AS
SELECT date_sold, sold_price, catalog_product_id, condition_id
FROM sales
WHERE invalid = 0 AND condition_id <= 3
ORDER BY date_sold DESC
Then replace the subquery with the view, like
SELECT b.brand_name, t.toy_id, t.toy_name, t.toy_number, tt.toy_type_name, cp.catalog_product_id, s.date_sold, s.condition_id, s.sold_price FROM brands AS b
LEFT JOIN toys AS t ON t.brand_id = b.brand_id
JOIN toy_types AS tt ON t.toy_type_id = tt.toy_type_id
LEFT JOIN catalog_products AS cp ON cp.toy_id = t.toy_id
LEFT JOIN toy_category AS tc ON tc.toy_category_id = t.toy_category_id
LEFT JOIN sales_view AS s ON s.catalog_product_id = cp.catalog_product_id
WHERE tc.toy_category_id = 1
GROUP BY t.toy_id, s.condition_id
ORDER BY t.toy_id ASC, s.condition_id ASC
Unfortunately, this change causes the query to no longer grab the most recent sale, and the sales price it returns is no longer the most recent.
Why is it that the table view doesn't return the same result as the same select as a subquery?
After reading just about every top-n-per-group stackoverflow question and blog article I could find, getting a query that actually worked was fantastic. But now that I need to extend the query one more step I'm running into performance issues. If anybody wants to sidestep the above question and offer some ways to optimize the original query, I'm all ears!
Thanks for any and all help.
The solution to the subquery performance issue was to use the answer provided here: Groupwise maximum
I thought that this approach could only be used when querying a single table, but indeed it works even when you've joined many other tables. You just have to left join the same table twice using the s.date_sold < s2.date_sold join condition and make sure the where clause looks for the null value in the second table's id column.

top 10 scorers by season

How I can get top 10 scorers by seasons.
So it shows last season top 10 scorers...
I've tryed left join into table, but it goes broken showing 2 player and counts all goals to first player.
My sqlfiddle:
http://sqlfiddle.com/#!9/b5d0a78/1
You got it almost right.
You want to group match_goals by player ID (match_player_id), but then you should not select goal_minute or any other per goal data.
After grouping by player, then you can create a column for COUNT(match_player_id) this will give you the number of goals, you can also use this column to order the results.
Your joins and conditions are correct I think.
EDIT
I think your schema needs a few tweaks: check this http://sqlfiddle.com/#!9/f5a75b/2
Basically create direct relations in the match_players and match_goals to the other tables.
I think the query you want looks like this:
SELECT p.*, count(*) as num_goals
FROM match_goals g INNER JOIN
match_players p
ON g.match_player_id = p.id INNER JOIN
matches m
ON m.id = p.match_id
WHERE p.is_deleted = 0 AND
g.is_own_goal = 0 AND
m.seasion_id = <last season id>
GROUP BY p.id
ORDER BY num_goals DESC
LIMIT 10;
Note that the teams table is not needed. The SELECT p.* is allowed because p.id (the GROUP BY key) is unique.

MySQL Differences with counts caused by joins

i have a problem in MySQL where I use the COUNT function for conditions. However, when combining this with joins, although I use grouping, the COUNT values include ALL rows, even the ones filtered out.
I'm providing a minimal working example, which however maybe does not make a practical sense or is designed smartly.
So assume I have 3 tables:
products with fields: productId, name, active (boolean)
teams with fields: teamId, name
rel_production with fields: teamId, productId
So basically I have products and teams with ids and names. Products can be active (lets say that means that they are still in production or so).
And then I have a relation which team is working on which product.
To explain my problem, assume the following minimal amount of data to clarify the problem is contained inside the tables:
products
teams
rel_production
Now the query that I want to do is, in plain english: "I want all teams that are working on exactly 2 products while atleast one product must be active."
The query in general works and is the following in mysql:
SELECT
teams.*,
"r_count:",
r_count.*,
COUNT(r_count.productId),
"r_active:",
r_active.*,
"p_active:",
p_active.*
FROM teams
INNER JOIN rel_production r_active ON r_active.teamId = teams.teamId
INNER JOIN products p_active ON p_active.productId = r_active.productId AND p_active.active
INNER JOIN rel_production r_count ON r_count.teamId = teams.teamId
GROUP BY teams.teamId, r_active.teamId
HAVING COUNT(r_count.productId) = 2 #4 is the problem!!!!!!!!!!!!!
Now them problem is with team 1. Because it is working on 2 active products, COUNT(r_count.productId) will be 4 and not 2. So my query will filter it out.
Here is the screenshot with the result without the HAVING clause:
I see why this happens, because the two inner joins on rel_production will cause 4 rows to be generated. But then they are merged always together to one using the GROUP BY. So what I need is the COUNT after the GROUP and not before.
How can I fix this?
Perform the filtering on teams in a separate subquery, and then join to that:
SELECT
t1.teamId,
t1.name
FROM teams t1
INNER JOIN
(
SELECT t1.teamId
FROM rel_production t1
INNER JOIN products t2
ON t1.productId = t2.productId
GROUP BY t1.teamId
HAVING COUNT(DISTINCT t1.productId) = 2 AND SUM(t2.active) > 0
) t2
ON t1.teamId = t2.teamId;
SQLFiddle

Select rows from one table according to the number of reps of the id in another

I have two tables, the users table and the records table, the relationship is one to many.
I want to select users with less than 3 records.
I am trying to use HAVING but it has not worked.
Thanks for the help you can give me.
example:
For example, I would like to get users 2 and 3 since they are the ones that have less than 3 records.
select u.id from users u left outer join records r on u.id=r.userid
group by u.id having count(r.userid) < 3
SELECT u.Id,u.Name
FROM users u
LEFT OUTER JOIN Record r ON r.User_Id= u.Id
HAVING COUNT(User_ID)<3
Use above query to get desire result.