i am watching a tutorial. There is a code which i don't understand what is supposed to do.
$sql = 'SELECT p.*,
a.screen_name AS author_name,
c.name AS category_name
FROM
posts p
LEFT JOIN
admin_users a ON p.author_id = a.id
LEFT JOIN
categories c ON p.category_id = c.id
WHERE
p.id = ?';
I read about the left joins but i didn't understand them. Can somebody please explain me the code i shared.
Thanks in advance!
Imagine you have two tables. One that stores the information about the programmers on your website, and the other table that keeps track of their online purchases.
PROGRAMMERS Table
+--------------------------------------------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Desire | 32 | 123 fake s| 3000.00 |
| 2 | Jamin | 25 | 234 fake s| 2500.00 |
| 3 | Jon | 23 | 567 fake s| 2000.00 |
| 4 | Bob | 30 | 789 fake s| 1500.00 |
| 5 | OtherGuy | 31 | 890 fake s| 1000.00 |
| 6 | DudeMan | 32 | 901 fake s| 500.00 |
+--------------------------------------------+
PURCHASES Table
+---------------------------------------------+
| ORDER_ID | PROG_ID | DATE | PRICE |
+-------------+---------+---------------------|
| 1 | 1 | 1-1-2017 | 100 |
| 2 | 2 | 1-2-2017 | 200 |
| 3 | 6 | 1-3-2017 | 300 |
+---------------------------------------------|
You decide you need to make a new table to consolidate this information to a table that contains
certain columns you want.
For example, you figure it would be nice for shipping purposes to have a table
that has the ID, the NAME, the PRICE, and the DATE columns.
Currently, the tables we have don't display all of that in a single table.
If we were to LEFT JOIN these tables, we would end up filling the desired columns
with NULL values where there is no information to join.
SELECT ID, NAME, PRICE, DATE
FROM PROGRAMMERS
LEFT JOIN PURCHASES
ON PROGRAMMERS.ID = PURCHASES.PROG_ID;
Notice that I'm selecting the columns I want from the starting table, then joining the right table
even though there might be missing information.
RESULTING TABLE
+-------------------------------------+
| ID | NAME | PRICE | DATE |
+----+----------+-----------------+---+
| 1 | Desire | 100 | 1-1-2017 |
| 2 | Jamin | 200 | 1-2-2017 |
| 3 | Jon | NULL | NULL |
| 4 | Bob | NULL | NULL |
| 5 | OtherGuy | NULL | NULL |
| 6 | DudeMan | 300 | 1-3-2017 |
+-------------------------------------+
For a visual representation of the difference between SQL JOINs check out
https://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins .
Related
I was reading about the right outer join from tutorialspoint. I know that when a right outer join is performed the first thing that happens is an inner join of the two tables and then any rows in the right table that are missing in the left table are given null values.
Example from tutorial:
Customers table:
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
| 7 | Muffy | 24 | Indore | 10000.00 |
+----+----------+-----+-----------+----------+
Orders table:
+-----+---------------------+-------------+--------+
|OID | DATE | CUSTOMER_ID | AMOUNT |
+-----+---------------------+-------------+--------+
| 102 | 2009-10-08 00:00:00 | 3 | 3000 |
| 100 | 2009-10-08 00:00:00 | 3 | 1500 |
| 101 | 2009-11-20 00:00:00 | 2 | 1560 |
| 103 | 2008-05-20 00:00:00 | 4 | 2060 |
+-----+---------------------+-------------+--------+
Query:
SELECT ID, NAME, AMOUNT, DATE
FROM CUSTOMERS
RIGHT JOIN ORDERS
ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
Result:
+------+----------+--------+---------------------+
| ID | NAME | AMOUNT | DATE |
+------+----------+--------+---------------------+
| 3 | kaushik | 3000 | 2009-10-08 00:00:00 |
| 3 | kaushik | 1500 | 2009-10-08 00:00:00 |
| 2 | Khilan | 1560 | 2009-11-20 00:00:00 |
| 4 | Chaitali | 2060 | 2008-05-20 00:00:00 |
+------+----------+--------+---------------------+
Why is the result of the right outer join the same as the original right table? How is this right join in anyway useful? I see it as pointless.
This isn't a useful query for RIGHT JOIN. Since all orders should have a valid customer (in fact, there should be a foreign key relationship between the Order and Customers tables), there will never be an order with no matching customer, so you'll never get any null values added.
I think they included this query just to contrast it with the almost identical query on the LEFT JOIN and FULL JOIN pages of the tutorial. Those queries show all orders, as well as all customers that don't have any orders (they have NULL in the AMOUNT and DATE columns.
To get the equivalent result with RIGHT JOIN you can simply swap the order of the tables:
SELECT ID, NAME, AMOUNT, DATE
FROM ORDERS
RIGHT JOIN CUSTOMERS
ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
Because LEFT JOIN and RIGHT JOIN are equivalent like this, most programmers just use LEFT JOIN.
This is not the right example in that case.To see something which is there in orders table but not in customers table the id should be something that is not present in customers,such as 8,9 etc.
Complete newbie to mySQL. So any help will be appreciated.
I have 3 tables -- carts, users, actions.
carts:
+------------+-------------+-------+
| cartId | session_id | userId|
+------------+-------------+-------+
users:
+----------+-------------+
| usedId | email |
+----------+-------------+
actions:
+-------------+------------------+---- ---------+
| session_id | impressionAction | impressionId |
+-------------+------------------+-----+--------+
In carts, there is one session_id per line.
In users, there is one userId per line.
In actions, there are multiple lines per session_id counting for all the actions for that session.
I would like to JOINthe three tables getting the output to be something like
+------+-------------+--------+------------------+--------------+-------+
userId | session_id | cartId | impressionAction | impressionId | email |
+------+-------------+--------+------------------+--------------+-------+
Where there will be multiple lines per userId and session_id; essentially a flattened file. I think if we JOIN carts and users on userId resulting in say A and then JOIN A and actions' onsession_id`, we are home.
A sample expected output is:
+------------+-------------+--------+------------------+--------------+---------+
userId | session_id | cartId | impressionAction | impressionId | email |
+------------+-------------+--------+------------------+--------------+---------+
| 1234 | abc3f45 | 0001 | LOGIN | 2032 |ab#yc.com|
| 1234 | abc3f45 | 0001 | ADD | 4372 |ab#yc.com|
| 1234 | abc3f45 | 0001 | ADD | 4372 |ab#yc.com|
| 1234 | abc3f45 | 0001 | SENDMAIL | ab#yc.com |ab#yw.com|
| 4567 | def4rg4 | 0002 | LOGIN | 2032 |db#yw.com|
| 4567 | def4rg4 | 0002 | ADD | 4372 |db#yw.com|
| 4567 | def4rg4 | 0002 | REMOVE | 3210 |db#yw.com|
+------------+-------------+--------+------------------+--------------+---------+**
I don't know how to JOIN 3 tables without one common key. I don't even know what type of join it is called.
Essentially, we are trying to join 3 tables with non-overlapping keys, gathering one common key through the first JOIN and then joining the intermediate with the third one. Is this called a CROSS JOIN? If no, is there a name?
Taken from your comment above
A USER may select many products, add them to their CART; a single
USER may have multiple CARTS and at the end of the event, they can
EMAIL the cart to themselves; the ACTIONS of the user are stored in
the actions table
This is how I see the structure (having in mind your data)
+---------------------+ +---------------------+ +---------------------+
| users | | carts | | actions |
+---------------------+ +---------------------+ +---------------------+
| user_id [PK] |--| | cart_id [PK] | | impression_id [PK] |
| email | |--| user_id [FK] | | action_name |
| | | product_id [FK] | |--| session_id [FK]* |
+---------------------+ | session_id [FK]* |--| | |
| | +---------------------+
+---------------------+
As you can see above, I'm joining first with carts and them with actions because only the table carts has both, user and session data.
The [FK]* next to the session_id on carts and actions could seem as a foreign key but in this case it's not - 'cause there's no separate table for sessions where it would be placed as an PK (primary key)
You asked about join - it is the same as inner join. INNER JOIN creates a new result table by combining column values of two tables (A and B) based upon the join-predicate. The query compares each row of A with each row of B to find all pairs of rows which satisfy the join-predicate.
This is a possible content of the tables
+------------------------+
| users |
+------------------------+
| id | email |
+------+-----------------+
| 1 | first#mail.org |
| 2 | second#mail.org |
| 3 | third#mail.org |
+------+-----------------+
+------------------------------------------+
| carts |
+------------------------------------------+
| id | user_id | product_id | session_id |
+------+---------+------------+------------+
| 1 | 1 | 5 | 1aaaa |
| 2 | 2 | 5 | 2ffff |
| 3 | 3 | 8 | 3ddddd |
| 4 | 1 | 5 | 1aaaaa |
| 5 | 3 | 9 | 3bbbbb |
| 6 | 1 | 6 | 1ccccc |
+------+---------+------------+------------+
+-------------------------------+
| actions |
+-------------------------------+
| id | name | session_id |
+------+-----------+------------+
| 1 | ADD | 1aaaa |
| 2 | ADD | 2ffff |
| 3 | SENDMAIL | 3ddddd |
| 4 | ADD | 3ddddd |
| 5 | SENDMAIL | 2ffff |
| 6 | ADD | 1aaaaa |
| 7 | REMOVE | 3ddddd |
| 8 | ADD | 1ccccc |
| 9 | ADD | 3bbbbb |
| 10 | SENDMAIL | 3bbbbb |
+------+-----------+------------+
As you can see, there are six products in the table carts and exactly six add actions in the table actions. Furthermore, as you can see user with an id=1 bought three products but not at the same time, since there are two sessions; user with an id=3 as well, bought these two products in different times etc...
The SQL statement
SELECT u.user_id, c.session_id, c.cart_id, a.impression_id, a.action_name, u.email
FROM users AS u
INNER JOIN carts AS c ON c.user_id = u.user_id
INNER JOIN actions AS a ON a.session_id = c.session_id
ORDER BY u.user_id, c.session_id, c.cart_id
Results:
+---------+------------+---------+---------------+-------------+-----------------+
| user_id | session_id | cart_id | impression_id | action_name | email |
+---------+------------+---------+---------------+-------------+-----------------+
| 1 | 1aaaa | 1 | 1 | ADD | first#mail.org |
| 1 | 1aaaa | 1 | 6 | ADD | first#mail.org |
| 1 | 1aaaa | 4 | 1 | ADD | first#mail.org |
| 1 | 1aaaa | 4 | 6 | ADD | first#mail.org |
| 1 | 1cccc | 6 | 8 | ADD | first#mail.org |
| 2 | 2ffff | 2 | 5 | SENDMAIL | second#mail.org |
| 2 | 2ffff | 2 | 2 | ADD | second#mail.org |
| 3 | 3bbbb | 5 | 9 | ADD | third#mail.org |
| 3 | 3bbbb | 5 | 10 | SENDMAIL | third#mail.org |
| 3 | 3dddd | 3 | 3 | SENDMAIL | third#mail.org |
| 3 | 3dddd | 3 | 4 | ADD | third#mail.org |
| 3 | 3dddd | 3 | 7 | REMOVE | third#mail.org |
+---------+------------+---------+---------------+-------------+-----------------+
Note: There's no guarantee for session uniqueness.
(Updated) Working SQL Fiddle
UPDATE: (Finding and deleting duplicates)
I've updated the SQL Fiddle in order to simulate duplicate records (when user added the same product within the same session). With the following statement you'll be able to retrieve those duplicated rows.
SELECT c.card_id, c.user_id, c.product_id, c.session_id, a.action_name, a.impression_id
FROM cards As c
INNER JOIN actions AS a ON a.session_id = c.session_id
GROUP BY c.user_id, c.product_id, c.session_id, a.action_name
HAVING count(*) > 1
Results:
+---------+------------+------------+------------+-------------+-----------------+
| card_id | user_id | product_id | session_id | action_name | impression_id |
+---------+------------+------------+------------+-------------+-----------------+
| 1 | 1 | 5 | 1aaaa | ADD | 1 |
| 6 | 1 | 6 | 1cccc | ADD | 8 |
+---------+------------+------------+------------+-------------+-----------------+
In the SELECT part of the statement above you may omit everything except card_id and impression_id. Deleting these two duplicates in one statement is a bit tricky since you can't modify the same table selected in a sub-query within the same query. I would avoid the tricky part in this case (which involves another inner sub-query) and would delete duplicates using separate statements as following
-- delete duplicates from cards
--
DELETE FROM WHERE card_id IN (1,6)
-- delete duplicates from actions
--
DELETE FROM WHERE card_id IN (1,8)
Even better, you could check if the user already has been added a selected product and don't add it twice.
Excuse my MySql syntax, as I don't know it :-p But this is the idea
SELECT u.userId, a.session_id, c.cartId, a.impressionAction, a.impressionId, u.email
FROM Carts c
JOIN Users u on u.userId = c.UserId
JOIN Actions a on a.session_id = c.session_id
This will just merge everything together, and you'll have duplicate cart records if you have many to 1 relationships
I have 3 tables to join and need some help to make it work, this is my schema:
donations:
+--------------------+------------+
| uid | amount | date |
+---------+----------+------------+
| 1 | 20 | 2013-10-10 |
| 2 | 5 | 2013-10-03 |
| 2 | 50 | 2013-09-25 |
| 2 | 5 | 2013-10-01 |
+---------+----------+------------+
users:
+----+------------+
| id | username |
+----+------------+
| 1 | rob |
| 2 | mike |
+----+------------+
causes:
+--------------------+------------+
| id | uid | cause | <missing cid (cause id)
+---------+----------+------------+
| 1 | 1 | stop war |
| 2 | 2 | love |
| 3 | 2 | hate |
| 4 | 2 | love |
+---------+----------+------------+
Result I want (data cropped for reading purposes)
+---------+-------------+---------+-------------+
| id | username | amount | cause |
+---------+-------------+---------+-------------+
| 1 | rob | 20 | stop war |
| 2 | mike | 5 | love |
+---------+-------------+-----------------------+
etc...
This is my current query, but returns double data:
SELECT i.*, t.cause as tag_name
FROM users i
INNER JOIN donations tti ON (tti.uid = i.id)
INNER JOIN causes t ON (t.uid = tti.uid)
EDIT: fixed sql schema on fiddle
http://sqlfiddle.com/#!2/0e06c/1 schema and data
How I can do this?
It seems your table's model is not right. There should be a relation between the Causes and Donations.
If not when you do your joins you will get duplicated rows.
For instance. Your model could look like this:
Donations
+--------------------+------------+
| uid | amount | date | causeId
+---------+----------+------------+
| 1 | 20 | 2013-10-10 | 1
| 2 | 5 | 2013-10-03 | 2
| 2 | 50 | 2013-09-25 | 3
| 2 | 5 | 2013-10-01 | 2
+---------+----------+------------+
causes:
+----------------------+
| id | cause |
+---------+------------+
| 1 | stop war |
| 2 | love |
| 3 | hate |
+---------+------------+
And the right query then should be this
SELECT i.*, t.cause as tag_name
FROM users i
INNER JOIN donations tti ON (tti.uid = i.id)
INNER JOIN causes t ON (t.id = tti.causeId)
Try this
SELECT CONCAT(i.username ,' ',i.first_name) `name`,
SUM(tti.amount),
t.cause AS tag_name
FROM users i
LEFT JOIN donations tti ON (tti.uid = i.id)
INNER JOIN causes t ON (t.uid = tti.uid)
GROUP BY i.id
Fiddle
You need to match the id from both the users and causes table at the same time, like so:
SELECT i.*, t.cause as tag_name
FROM users i
INNER JOIN donations tti ON (tti.uid = i.id)
INNER JOIN causes t ON (t.uid = tti.uid and t.id = i.id)
Apologies for formatting, I'm typing this on a phone.
I've been struggling with a query which selects from multiple tables. My original query was incredibly slow (53 seconds). From reading up, I'm now reasonably sure that I need to create an inner query to limit the data which is iterated over. But I'm not sure how to use the result of the subquery (inner query) when using more than 2 tables. Below are some dummy tables:
+-------+---------------------+------------+
| tr_id | tr_datecreated | tr_depart |
+-------+---------------------+------------+
| 1 | 2011-07-31 00:00:00 | 2011-08-20 |
| 2 | 2011-08-01 00:00:00 | 2011-08-30 |
| 3 | 2011-08-02 00:00:00 | 2011-09-01 |
+-------+---------------------+------------+
+------+--------+---------+---------+
| p_id | p_trid | p_name | p_lname |
+------+--------+---------+---------+
| 1 | 1 | Geoff | Thingy |
| 2 | 1 | Mildred | Thingy |
| 3 | 1 | Garry | Thingy |
| 4 | 2 | Linda | Doobrey |
| 5 | 2 | Kev | Doobrey |
| 6 | 3 | John | Wotsit |
| 7 | 3 | Jill | Wotsit |
+------+--------+---------+---------+
+------+--------+----------+
| h_id | h_trid | h_dest |
+------+--------+----------+
| 1 | 1 | France |
| 2 | 1 | Spain |
| 3 | 2 | Italy |
| 4 | 3 | Portugal |
+------+--------+----------+
I want to get a result such as:
+-------+---------------------+------------+---------+---------+----------+
| tr_id | tr_datecreated | tr_depart | p_name | p_lname | h_dest |
+-------+---------------------+------------+---------+---------+----------+
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Geoff | Thingy | France |
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Geoff | Thingy | Spain |
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Mildred | Thingy | France |
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Mildred | Thingy | Spain |
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Garry | Thingy | France |
| 1 | 2011-07-31 00:00:00 | 2011-08-20 | Garry | Thingy | Spain |
| 2 | 2011-08-01 00:00:00 | 2011-08-30 | Linda | Doobrey | Italy |
| 2 | 2011-08-01 00:00:00 | 2011-08-30 | Kev | Doobrey | Italy |
| 3 | 2011-08-02 00:00:00 | 2011-09-01 | John | Wotsit | Portugal |
| 3 | 2011-08-02 00:00:00 | 2011-09-01 | Jill | Wotsit | Portugal |
+-------+---------------------+------------+---------+---------+----------+
where we get a separate row for each person for each holiday destination.
My original effort was in the form of:
SELECT tr_id, tr_datecreated, tr_depart, p_name, p_lname, h_dest
FROM transaction, people, holiday
WHERE tr_id = p_trid
AND tr_id = h_trid
AND tr_datecreated >= "2010-12-12 00:00:00"
AND tr_datecreated <= "2012-12-12 00:00:00"
I think that this created a huge number of cross joins and the query ran very slowly.
Seeing as the tr_id is being referenced a number of times I wanted to do an inner query which reduced the number of rows that everything else was compared to.
So the inner query part will be:
SELECT tr_id WHERE tr_datecreated >= "2010-12-12 00:00:00"
AND tr_datecreated <= "2012-12-12 00:00:00"
How would I create my desired table which I would want to compare both the p_trid and the h_trid against the same inner query without running that inner query twice (if possible)?
Would inner joins help in this situation? (I have read through but haven't fully absorbed it yet).
Grateful for any advice and suggestions here. The database is large and I need to be efficient.
Edit
Indexes:
tr_id, h_id and p_id are all primary keys
Result of EXPLAIN
+----+-------------+--------------+--------+---------------+---------+---------+---------------------+------+--------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+--------+---------------+---------+---------+---------------------+------+--------------------------------+
| 1 | SIMPLE | holiday | ALL | NULL | NULL | NULL | NULL | 4 | |
| 1 | SIMPLE | people | ALL | NULL | NULL | NULL | NULL | 7 | Using where; Using join buffer |
| 1 | SIMPLE | transactions | eq_ref | PRIMARY | PRIMARY | 4 | db.people.p_trid | 1 | Using where |
+----+-------------+--------------+--------+---------------+---------+---------+---------------------+------+--------------------------------+
I think that this should work. Let me know if it works.
Total Query
SELECT t.id, t.date, t.depart, p.p_name, p.p_lname, h.h_dest
FROM
(SELECT tr_id 'id', tr_datecreated 'date', tr_depart 'depart' FROM transaction
WHERE DATE(tr_datecreated) BETWEEN DATE("2010-12-12 00:00:00")
AND DATE("2012-12-12 00:00:00")) t
JOIN people p ON t.id = p.p_trid
JOIN holiday h ON t.id = h.h_trid;
Inner Query
(SELECT tr_id 'id', tr_datecreated 'date', tr_depart 'depart' FROM transaction
WHERE DATE(tr_datecreated) BETWEEN DATE("2010-12-12 00:00:00")
AND DATE("2012-12-12 00:00:00"))
Edit: Subquery explanation
The subquery selects the id, date created, and depart columns from the transaction table for the date range that you listed above. The 't' outside the right paren at the end of query lets you alias the inner query so you can use its data above. Also, where I have 'id','date', and 'depart' inside the subquery is also aliasing. It lets you use those values without typing out the full column name.
Hope this helped.
have you tried joins?
SELECT tr.tr_id, tr.tr_datecreated, tr.tr_depart, p.p_name, p.p_lname, h.h_dest
FROM transaction tr
join people p on tr.tr_id = p.p_trid
join holiday h on tr.tr_id = h.h_trid
WHERE tr_datecreated >= "2010-12-12 00:00:00"
AND tr_datecreated <= "2012-12-12 00:00
haven't tested this yet but that's the general idea.
I suggest to add an index on people.p_trid and holiday.h_trid. The EXPLAIN clearly shows that there is no index used for both tables.
Also make sure that datatype of transactions.tr_id, people.p_trid and holiday.h_trid is the same.
First off, sorry if this is a near enough duplicate. I've found this question, which nearly does what I want, but I couldn't wrap my head around how to alter it to my needs.
I've got these 3 tables:
cs_Accounts:
+----+-----------------------------+-------------+
| id | email | username |
+----+-----------------------------+-------------+
| 63 | jamasawaffles#googlil.com | jamwaffles2 |
| 64 | jamwghghhfles#goomail.com | jamwaffles3 |
| 65 | dhenddfggdfgetal-pipdfg.com | dhendu9411 |
| 60 | jwapldfgddfgfffles.co.uk | jamwaffles |
+----+-----------------------------+-------------+
cs_Groups:
+----+-----------+------------+-------------+
| id | low_limit | high_limit | name |
+----+-----------+------------+-------------+
| 1 | 0 | 0 | admin |
| 2 | 1 | 50 | developer |
| 3 | 76 | 100 | reviewer |
| 4 | 51 | 75 | beta tester |
| 5 | 1 | 50 | contributor |
+----+-----------+------------+-------------+
cs_Permissions:
+----+---------+----------+
| id | user_id | group_id |
+----+---------+----------+
| 4 | 60 | 4 |
| 3 | 60 | 1 |
| 5 | 60 | 2 |
| 6 | 62 | 1 |
| 7 | 62 | 3 |
+----+---------+----------+
I've been wrestling with a 3 way join for hours now, and I can't get the results I want. I'm looking for this behaviour: a row will be returned for every user from cs_Accounts where there is a row in cs_Permissions that contains their ID and the ID of a group from cs_Groups, as well as the group with the group_id has a high_lmiit and low_limit in a range I can specify.
Using the data in the tables above, we might end up with something like this:
email username cs_Groups.name
----------------------------------------------------------
jwapldfgddfgfffles.co.uk jamwaffles admin
jwapldfgddfgfffles.co.uk jamwaffles developer
jwapldfgddfgfffles.co.uk jamwaffles beta tester
dhenddfggdfgetal-pipdfg.com dhendu9411 admin
dhenddfggdfgetal-pipdfg.com dhendu9411 reviewer
There is an extra condition, however. This condition is where rows are only selected if the group the user belongs to has a high_limit and low_limit with values I can specify using a WHERE clause. As you can see, the table above only contains users with rows in the permissions table.
This feels a lot like homework but with a name like James I'm always willing to help.
select a.email,a.username,g.name
from cs_Accounts a
inner join cs_Permissions p on p.user_id = a.id
inner join cs_Groups g on g.id = p.Group_id
where g.low_limit > 70
and g.high_limt < 120
This is the query
SELECT ac.email, ac.username, gr.name
FROM cs_Accounts AS ac
LEFT JOIN cs_Permissions AS per ON per.user_id = ac.id
INNER JOIN cs_Groups AS gr ON per.user_id = gr.id
You can add a WHERE clause to this query if you want