mysql query help to fetch data by joining multiple tables - mysql

I have following tables:
base:
id | domain
extended:
id | domain | country_code
countries:
id | country_code | country_name
banned_domains:
id | domain
I will have several thousands (more than 500K) of domains in banned_domains. Now I need to fetch data "domain, country_code and country_name" which do not exist on banned_domains list. I am not so good at the MySQL JOINS, can anyone guide me for the proper query.

SELECT b.domain, ex.country_code, c.country_name FROM base b
INNER JOIN extended ex ON b.domain=ex.domain
INNER JOIN countries c ON ex.country_code=c.country_code
WHERE b.domain NOT IN (SELECT domain FROM banned_domains);

You can use this query .
select b.domain , e.country_code , c.country_name from base b join extended e on b.domain = e.domain join countries c on e.country_code = c.country_code and b.domain not in (select domain from banned_domains);
Try this link http://sqlfiddle.com/#!2/f78ea/1 .

Related

SQL SELECT name by id

I need help with a sql query.
I have these 2 tables:
player_locations:
ID | playerid | location <- unqiue key
---|-----------------------
1 | 1 | DOWNTOWN
and users:
ID | playername | [..]
----|--------------------
1 | example1 | ...
I need a select to get the users.playername from the player_locations.playerid. I have the unique location to get the player_locations.playerid.
Pseudo query:
SELECT playername
FROM users
WHERE id = player_locations.playerid
AND player_locations.location = "DOWNTOWN";
The output should be example1.
This is just a simple INNER JOIN. The general syntax for a JOIN is:
SELECT stuff
FROM table1
JOIN table2 ON table1.relatedColumn = table2.relatedColumn
In your case, you can relate the two tables using the id column from users and playerid column from player_locations. You can also include your 'DOWNTOWN' requirement in the JOIN statement. Try this:
SELECT u.playername
FROM users u
JOIN player_locations pl ON pl.playerid = u.id AND pl.location = 'DOWNTOWN';
EDIT
While I personally prefer the above syntax, I would like you to be aware of another way to write this which is similar to what you have now.
You can also select from multiple tables by using a comma in your FROM clause to separate them. Then, in your WHERE clause you can insert your conditions:
SELECT u.playername
FROM users u, player_locations pl
WHERE u.id = pl.playerid AND pl.location = 'DOWNTOWN';
Here is the solution.
SELECT
playername
FROM users
WHERE id = (SELECT id FROM player_locations WHERE location='DOWNTOWN')
I have a idea, try this:
SELECT playername
FROM users
WHERE id IN (SELECT DISTINCT playerid FROM player_location WHERE location LIKE "DOWNTOWN");

Free search on multiple tables using JOIN

I have a DB of Students who have a fullname, a location, and a list of schools they frequented.
"student" table
id | fullname | location
------------------------
"location" table
id | zipcode | city
-------------------
"school" table
id | name
---------
"student_school" table (which holds two foreign keys on school and user to create for each user a list of schools)
id | id_student | id_school
---------------------------
I want to perform a search through the students comparing the search term with student.fullname, location.zipcode, location.city, school.name and return all the students matching one (or more) of these conditions.
Note that student can have a null location, so we need an extern join.
Here is example of matching based on regular expressions:
SELECT distinct s.id, s.fullname
FROM student_school ss
JOIN student s ON s.id = ss.id_student
LEFT JOIN LOCATION l ON s.LOCATION = l.id
JOIN school sc ON ss.id_school = sc.id
WHERE (s.fullname RLIKE 'Sasha.*') or
(ifnull(l.zipcode RLIKE '100.*', 0)) or
(ifnull(l.city RLIKE 'New.*', 0)) or
(sc.name RLIKE '.*2')
And here is complete SQL fiddle
So the general idea is to join all student data, filter rows matching at least one criterion and use distinct to group data and avoid duplicating of results.
Update:
To include students with no school records you may use following FROM phrase:
student_school ss
RIGHT JOIN student s ON s.id = ss.id_student
LEFT JOIN LOCATION l ON s.LOCATION = l.id
LEFT JOIN school sc ON ss.id_school = sc.id

Mysql select on non linked tables

I've got two tables, that are not linked the standard way (I'm aware this isn't a good way to do it)
lets say the tables are setup like the below
Table:
component
fields:
cid, cname, rangeid, company
Table: ranges
fields:
rid, rangename, year
While this is quite simple in a relational DB, i'm not too sure of the cleanest way to do this otherwise (remaking the DB is not an option).
the basic query I need is.
select * from component where range.year = '2014' and company = 'xxx'
any advice would be greatly appreciated.
Is this what you're looking for?
SELECT a.cid, a.cname, a.rangeid, a.company, b.rid, b.rangename, b.year
FROM component a
JOIN ranges b ON
b.rid = a.rangeid
WHERE b.year = 2014
AND a.company = 'xxx'
Result
| CID | CNAME | RANGEID | COMPANY | RID | RANGENAME | YEAR |
------|-----------|---------|---------|-----|-----------|------|
| 1 | Component | 1 | xxx | 1 | Range | 2014 |
Demo
If a range from component may not exist in ranges, then use a LEFT JOIN.
JOIN the two tables:
select c.cname, r.rangename, r.year, ...
from component AS c
INNER JOIN ranges AS r ON c.rangeid = r.rid
where r.year = '2014'
and c.company = 'xxx';
Note that: You can JOIN any tables normally, even if they haven't any relation between them, just put the condition in the ON clause, just like in your case. But, you have to ensure that indexes are setup correctly, see this page fore more information:
Multiple-Column Indexes
JOIN is what you are looking for :
select *
from component
inner join ranges on rid = rangeid and year = 2014
where company = 'xxx'

SQL statement for join but not in other table

I have two tables: customer and mailing :
+==========+ +=============+
| customer | | mailing |
+==========+ +=============+
| id | | id |
+----------+ +-------------+
| name | | customer_id |
+----------+ +-------------+
| mailing_id |
+-------------+
Every time I send a mailing to a customer, I add a row in the mailings table with that mailing id. One mailing can be sent to multiple customers.
I want to have a sql call that returns all customers that have not yet received a certain mailing. How to ?
I am using mysql
select * from customer where id not in (
select customer_id from mailing where mailing_id = #mailing_id
)
Something like
Select c.ID, c.Name
From Customers C
left Join mailing m On c.id = m.customer_id
where m.customer_id is null
SELECT * FROM customers c
JOIN mailings m
ON c.id = m.id
WHERE NOT EXISTS (
SELECT id
FROM mailings i
WHERE i.id = c.id
GROUP BY i.id
)
What you describe is called an ANTI JOIN. Usually there are three different ways for formulating it in SQL: A NOT IN condition with a subquery, a NOT EXISTS condition with a correlated subquery, or a LEFT JOIN with a NOT NULL condition.
So for your query the possibilities are:
SELECT *
FROM customer
WHERE id NOT IN
( SELECT customer_id
FROM mailing)
SELECT *
FROM customer c
WHERE NOT EXISTS
( SELECT customer_id
FROM mailing m
WHERE m.customer_id = c.id)
SELECT *
FROM customer c
LEFT JOIN mailing m ON c.id = m.customer_id
WHERE m.customer_id IS NULL
This blog post compares the different possibilities with MySQL 5.1. According to it, LEFT JOIN / IS NULL and NOT IN are faster than NOT EXISTS.
However, you should try for yourself which one is the fastest. That always depends on your data, indexes, ...

MySQL join to return distinct IDs linked from another table

Let's say I have three tables:
LOCATIONS - a store can belong to multiple locations and a location can have multiple stores
+-------------+----------+
| LOCATION_ID | STORE_ID |
+-------------+----------+
STORES - only one row per store, every store has only one manager ID
+----------+------------+
| STORE_ID | MANAGER_ID |
+----------+------------+
EMPLOYEES - a manager can have multiple employees, and employees can belong to more than one manager
+-------------+-------------+
| MANAGER_ID | EMPLOYEE_ID |
+-------------+-------------+
And for a given location (e.g. LOCATION_ID = 999), I want to get all the employees managed at stores at that location.
This gets me the list of managers that belong to stores in that location:
SELECT s.MANAGER_ID FROM LOCATIONS l
INNER JOIN STORES s
ON s.STORE_ID = l.STORE_ID
WHERE l.LOCATION_ID = 999;
What I actually want is ALL the distinct EMPLOYEE_IDs that are linked to the managers that query spits out.
What additional join can I add in the same query to get that?
SELECT DISTINCT E.EMPLOYEE_ID
FROM LOCATIONS L
INNER JOIN STORES S ON S.STORE_ID = L.STORE_ID
INNER JOIN EMPLOYEES E ON S.MANAGER_ID = E.MANAGER_ID
WHERE L.LOCATION_ID = 999;
Adding INNER JOIN Employees e ON s.MANAGER_ID = e.MANAGER_ID should get you the employees.
But I notice you're asking for how to select all the distinct employee IDs. Change your SELECT clause to SELECT DISTINCT e.EMPLOYEE_ID, rather than returning the store managers' IDs.
RedFilter's answer spells it out nicely. :)
SELECT e.EMPLOYEE_ID ... INNER JOIN EMPLOYEES e ON e.MANAGER_ID = s.MANAGER_ID ...
You can add the DISTINCT keyword before the employee ID, however if the data is properly normalized that shouldn't be necessary.