MySQL inner join among three tables syntax - mysql

My tables:
mysql> select * from pvf_order;
+------+------------+------+
| oid | orderdate | cid |
+------+------------+------+
| 1001 | 2014-02-10 | 1 |
10 rows in set (0.00 sec)
mysql> select * from pvf_order_item;
+------+-----+----------+
| oid | pid | quantity |
+------+-----+----------+
| 1001 | 1 | 2 |
18 rows in set (0.00 sec)
mysql> select * from pvf_product;
+-----+----------------------+----------------+--------+--------------+
| pid | prod_desc | Prod_finish | price | prod_line_id |
+-----+----------------------+----------------+--------+--------------+
| 1 | End Table | Cherry | 175.00 | 1 |
8 rows in set (0.01 sec)
Right now my query has been variations of:
SELECT
pvf_order.cid,
pvf_order.orderdate,
pvf_product.prod_desc,
pvf_order_item.quantity,
pvf_product.price
FROM pvf_order
INNER JOIN pvf_order.oid=pvf_order_item.oid
INNER JOIN pvf_order_item.pid=pvf_product.pid
WHERE YEAR(pvf_order.orderdate)=2014 AND MONTH(pvf_order.orderdate)=10;
I just don't know exactly where I'm going wrong. I edited some of the info out just to avoid a big wall of text, but I hope the general idea is there. Any help is appreciated!

Check JOIN sintaxis, also use ALIAS for table names
SELECT
o.cid,
o.orderdate,
p.prod_desc,
oi.quantity,
p.price
FROM pvf_order o
INNER JOIN pvf_order_item oi
ON o.oid = oi.oid
INNER JOIN pvf_product p
ON pvf_o.pid = p.pid
WHERE YEAR(o.orderdate) = 2014 AND MONTH(o.orderdate) = 10;
Also instead of use Year and Month function, you can simplify to one single comparasion operation.
WHERE date_format(o.orderdate, '%Y-%m') = '2014-10'

Related

Get records from one table and a corresponding table

I have two tables:
orders
poid | user | pid | payment_id
1 | 1 | 1 | abc123
2 | 2 | 2 | def345
orders_addon
poaid | user | poid | pid
1 | 1 | 1 | 3
2 | 1 | 1 | 5
One represents orders, the second one represent addons a user can add to his order.
There is always a row in orders and it can occur that there is no matching orders_addon for an order.
I'm looking for a query that returns matching rows from orders and orders_addon if there are matching ones.
SELECT user,pid FROM ... WHERE payment_id = 'abc123'
Should return
user | pid
1 | 1
1 | 3
1 | 5
And the same query should only return results from the orders table if there is no matching record in the orders_addon table.
SELECT user,pid FROM ... WHERE payment_id = 'def345'
user | pid
2 | 2
I reckon this could be done using UNION but then I wouldn't be able to match the tables and it would become a problem since the orders_addon table doesn't have a payment_id
Use LEFT JOIN WITH IF STATMENT
mysql> ( SELECT u.user,IFNULL(ua.pid ,u.pid) as pid
FROM orders u
inner JOIN orders_addon ua on ua.poid=u.poid
WHERE u.payment_id = 'abc123'
)
union all
( SELECT u.user,u.pid
from orders u
where u.payment_id = 'def345'
);
+------+------+
| user | pid |
+------+------+
| 1 | 3 |
| 1 | 5 |
| 2 | 2 |
+------+------+
3 rows in set (0.00 sec)
mysql> ( SELECT u.user,IFNULL(ua.pid ,u.pid) as pid
FROM orders u
inner JOIN orders_addon ua on ua.poid=u.poid
WHERE u.payment_id = 'def345'
)
union all
( SELECT u.user,u.pid
from orders u
where u.payment_id = 'def345'
);
+------+------+
| user | pid |
+------+------+
| 2 | 2 |
+------+------+
1 row in set (0.00 sec)

How could I use join query to find the intersection

I want to find the users who haven't make any order
My idea is that, Get all user ids and substract the unique ids in orders table
How could I convert it in MySQL query syntax.
mysql> select * from users;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
mysql> select * from orders;
+------+---------+--------+
| id | user_id | amount |
+------+---------+--------+
| 1 | 1 | 10.00 |
| 1 | 2 | 5.00 |
+------+---------+--------+
2 rows in set (0.00 sec)
The idea is to make make a left join between users (left table) and orders table.
Then from this joined table you need to filter those records which don't have any order. So in this case orders.id would be NULL.
SELECT
users.id
FROM users
LEFT JOIN orders
ON users.id = orders.user_id
WHERE orders.id IS NULL
Visual Understanding:
SQL Joins explained better here.
select * from users where id not in (select user_id from orders)

Nested query in From clause syntax and performance

I'm having two tables: one for user information, the second for mapping some relation between users (two column table with two ids, from id to id relation)
I'm trying to find for a specific userid all his users' relations ids (inner select) and then get more info about them by joining to a table which has more info to show.
Given the following error:
Error: #1064 - You have an error in your SQL syntax; check the manual list that corresponds to your mySQL server version for the right syntax to use near ') AS i Limit 0,30' at line 6
What wrong with my query?
Is this query is okay in terms of performance, or there are other way to do so?
Query:
SELECT i.*
FROM
((SELECT uc.contactId
FROM tbl_users AS u
JOIN tbl_users_contacts AS uc ON u.Id = uc.userId
WHERE uc.userId =1) AS contacts_ids JOIN tbl_users AS u
ON contacts_ids.contactId = u.Id) AS i;
Edit: Fixed to:
SELECT *
FROM
((SELECT uc.contactId
FROM tbl_users AS u
JOIN tbl_users_contacts AS uc ON u.Id = uc.userId
WHERE uc.userId =1) AS contacts_ids JOIN tbl_users AS u
ON contacts_ids.contactId = u.Id);
Don't know why the final As i was a problem, so I ask for question 2 mainly for this post.
Consider the following
mysql> create table tbl_users ( iduser int,name varchar(100),email varchar(100));
Query OK, 0 rows affected (0.10 sec)
mysql> insert into tbl_users values
-> (1,'A','a#a.com'),
-> (2,'B','b#b.com'),
-> (3,'C','c#c.com'),
-> (4,'D','d#d.com'),
-> (5,'E','e#e.com');
Query OK, 5 rows affected (0.09 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> create table contacts (iduser int, contactid int );
Query OK, 0 rows affected (0.14 sec)
mysql> insert into contacts values
-> (1,2),(1,3),(1,5),(2,1),(2,5),(3,1),(3,4);
mysql> select * from tbl_users ;
+--------+------+---------+
| iduser | name | email |
+--------+------+---------+
| 1 | A | a#a.com |
| 2 | B | b#b.com |
| 3 | C | c#c.com |
| 4 | D | d#d.com |
| 5 | E | e#e.com |
+--------+------+---------+
5 rows in set (0.00 sec)
mysql> select * from contacts ;
+--------+-----------+
| iduser | contactid |
+--------+-----------+
| 1 | 2 |
| 1 | 3 |
| 1 | 5 |
| 2 | 1 |
| 2 | 5 |
| 3 | 1 |
| 3 | 4 |
+--------+-----------+
7 rows in set (0.00 sec)
Now as we can see userid = 1 has 3 contacts and we can get them as
select u.* from tbl_users u
join contacts c on c.contactid = u.iduser
where c.iduser = 1 ;
The output will be as
+--------+------+---------+
| iduser | name | email |
+--------+------+---------+
| 2 | B | b#b.com |
| 3 | C | c#c.com |
| 5 | E | e#e.com |
+--------+------+---------+
To boost up the performance you may add the following indexes
alter table tbl_users add index userid_idx(iduser);
alter table contacts add index cu_idx(iduser,contactid);
Change the table and column name into the query as per your need.

How do I run this MySQL JOIN query?

Let's say I have 2 tables.
The first table is a list of personas. A user can have many personas.
mysql> select id, user_id, name from personas_personas;
+----+---------+--------------+
| id | user_id | name |
+----+---------+--------------+
| 8 | 1 | startup |
| 9 | 1 | nerd |
| 10 | 1 | close |
| 12 | 2 | Nerd |
| 13 | 2 | Startup |
| 14 | 2 | Photographer |
+----+---------+--------------+
6 rows in set (0.00 sec)
Now, I have another table called "approvals".
mysql> select id, from_user_id, to_user_id, persona_id from friends_approvals;
+----+--------------+------------+------------+
| id | from_user_id | to_user_id | persona_id |
+----+--------------+------------+------------+
| 2 | 1 | 2 | 8 |
| 3 | 1 | 2 | 9 |
+----+--------------+------------+------------+
2 rows in set (0.00 sec)
If from_user wants to approve to_user to a persona, then a record is inserted.
I'm trying to do this query...
Given a user, find all its personas. Then, for each persona, determine if it's approved for a certain to_user. If so, return is_approved=1 in the result set. Otherwise, return is_approved=0 in the result set.
So this is where I start:
SELECT *
FROM personas_personas
WHERE user_id = 1
LEFT JOIN friends_approvals ON
...but i don't know where to go from here.
So, the final result set should have all the columns in the personas_personas table, and then also is_approved for each of the results.
SELECT
pp.*,
CASE
WHEN exists (
SELECT
*
FROM
friends_approvals fa
WHERE
fa.from_user_id = pp.user_id AND
fa.persona_id = pp.id AND
fa.to_user_id = 2
)
THEN 1
ELSE 0
END as is_approved
FROM
personas_personas pp
WHERE
pp.user_id=1
Or, depending on your taste:
SELECT
pp.*,
CASE
WHEN fa.from_user_id IS NOT NULL
THEN 1
ELSE 0
END as is_approved
FROM
personas_personas pp
LEFT OUTER JOIN friends_approvals fa ON
pp.user_id = fa.from_user_id AND
pp.id = fa.persona_id AND
fa.to_user_id = 2
WHERE
pp.user_id=1
If I'm understanding your needs correctly, you can do this:
SELECT personas_personas.*,
CASE WHEN friends_approvals IS NULL THEN 0 ELSE 1 END AS is_approved
FROM personas_personas
LEFT
OUTER
JOIN friends_approvals
ON friends_approvals.from_user_id = ...
AND friends_approvals.to_user_id = personas_personas.user_id
AND friends_approvals.persona_id = personas_personas.id
WHERE personas_personas.user_id = ...
;
That will find every personas_personas record with the specified user_id, together with an indicator of whether that user, in that persona, has been "approved" by a specified from_user_id.
(If that's not what you want, then please clarify!)

help with query over relation table

I'm trying to knock the rust off my SQL skills and need some help with the following query. The database i'm currently using is mysql.
I want to retrieve all the FlashCards that are assigned BOTH 'tag2' and 'tag4'. Based on the contents of the existing table (as seen in the excerpt below) the query should return two rows: FlashCard_ID 1 and 2.
How would I formulate this query? It's been a while since I've had to do something like this.
mysql> select * from flashcard;
+--------------+------------+----------+
| FLASHCARD_ID | QUESTION | ANSWER |
+--------------+------------+----------+
| 1 | Question 1 | Answer 1 |
| 2 | Question 2 | Answer 2 |
| 3 | Question 3 | Answer 3 |
+--------------+------------+----------+
3 rows in set (0.00 sec)
mysql> select * from tag;
+--------+------+
| TAG_ID | NAME |
+--------+------+
| 1 | tag1 |
| 2 | tag2 |
| 3 | tag3 |
| 4 | tag4 |
| 5 | tag5 |
+--------+------+
5 rows in set (0.00 sec)
mysql> select * from flashcard_tags;
+--------+--------------+
| TAG_ID | FLASHCARD_ID |
+--------+--------------+
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 2 | 2 |
| 4 | 2 |
| 5 | 2 |
+--------+--------------+
6 rows in set (0.00 sec)
SELECT f.*
FROM (
SELECT flashcard_id
FROM tags t
JOIN flashcard_tags ft
ON ft.tag_id = t.tag_id
WHERE t.name IN ('tag2', 'tag4')
GROUP BY
flashcard_id
HAVING COUNT(*) = 2
) ft
JOIN flashcard f
ON f.flashcard_id = ft.flashcard_id
SELECT f.*
FROM flashcard f
INNER JOIN flashcard_tags ft1 ON f.FLASHCARD_ID = ft1.FLASHCARD_ID
INNER JOIN tag t1 ON ft1.TAG_ID = t1.TAG_ID AND t1.NAME = 'tag2'
INNER JOIN flashcard_tags ft2 ON f.FLASHCARD_ID = ft2.FLASHCARD_ID
INNER JOIN tag t2 ON ft2.TAG_ID = t2.TAG_ID AND t2.NAME = 'tag4'
Here's another query that works. This one doesn't use a subquery and is what I ended up using in my Hibernate code.
select fc.FLASHCARD_ID,
fc.QUESTION,
fc.ANSWER
from FLASHCARD fc
inner join FLASHCARD_TAGS fc_t
on fc.FLASHCARD_ID=fc_t.FLASHCARD_ID
inner join TAG t
on fc_t.TAG_ID=t.TAG_ID
where t.Name in ('tag2', 'tag4')
group by fc.FLASHCARD_ID
having count(t.TAG_ID)=2