How could I use join query to find the intersection - mysql

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)

Related

how to get count of distinct row in mysql without using DISTINCT keyword

i am trying to count of the distinct row from a mysql table without using distinct keyword.
i am able to get the number of duplicate row but not total count
mysql> select customer_fname, count(1) from customers group by customer_fname;
+----------------+----------+
| customer_fname | count(1) |
+----------------+----------+
| Mildred | 26 |
........................
.......................
| Wayne | 29 |
| William | 98 |
| Willie | 28 |
| Zachary | 34 |
+----------------+----------+
200 rows in set (0.01 sec)
mysql>
i should get the count as 200.
You could use count(*)
select customer_fname, count(*)
from customers
group by customer_fname;
and if you need the duplicate
select customer_fname, count(*)
from customers
group by customer_fname
having count(*) > 1;
for the total count without distint keyword then you could use a subquery
select count(*) from (
select customer_fname, count(*)
from customers
group by customer_fname) t
Using count(distinct you can get the unique name count as below:
select count(distinct customer_fname) as uniquenamecount
from customers;
Perhaps you are after found_rows(). for example
drop table if exists t;
create table t(id int);
insert into t values
(1),(1),(2),(2),(2);
select sql_calc_found_rows id,count(*) from t group by id;
+------+----------+
| id | count(*) |
+------+----------+
| 1 | 2 |
| 2 | 3 |
+------+----------+
2 rows in set (0.02 sec)
select found_rows();
+--------------+
| found_rows() |
+--------------+
| 2 |
+--------------+
1 row in set (0.00 sec)
see https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_found-rows

how to use sum function with join in MySQL

select sum(bales) as bales
from receive_bardana
join receive_wheat
on receive_bardana.id = receive_wheat.id
where id=1
my result is showing wrong output
Your query 1)should not even syntax given id is ambiguous in the where clause 2) the joined table is pointless since you don't use anything from it in the select 3) From the little information you have provided in the question there is a 1 to many relationship between receive_bardana and receive_wheat which means that the sum is over all the joined rows for example
create table receive_bardana(id int,bales int);
create table receive_wheat(id int);
insert into receive_bardana values (1,10),(2,20);
insert into receive_wheat values(1),(1),(2),(2),(2);
select *
from receive_bardana
join receive_wheat
on receive_bardana.id = receive_wheat.id
where receive_bardana.id;
Result
+------+-------+------+
| id | bales | id |
+------+-------+------+
| 1 | 10 | 1 |
| 1 | 10 | 1 |
| 2 | 20 | 2 |
| 2 | 20 | 2 |
| 2 | 20 | 2 |
+------+-------+------+
5 rows in set (0.00 sec)
and with your (fixed) query
select sum(bales) as bales
from receive_bardana
join receive_wheat
on receive_bardana.id = receive_wheat.id
where receive_bardana.id;
the sum correctly returns
+-------+
| bales |
+-------+
| 80 |
+-------+
1 row in set (0.00 sec)
Which explains fully the 'problem' you are having.
If you want a answer to what you are trying to do I suggest you raise a new question describing what you are trying to do rather than just saying this lump of code does not do as I expect (in fact it does what I expect and is not 'wrong')

Mysql query joining two tables where entry might not exist in one of the tables

I have 2 tables, like this:
mysql> select * from table1;
+------+------+
| id | name |
+------+------+
| 1 | joe |
| 2 | sue |
| 3 | ben |
| 2 | dick |
+------+------+
4 rows in set (0.00 sec)
mysql> select * from table2;
+------+-----------+
| id | something |
+------+-----------+
| 1 | whatever |
| 1 | whatever2 |
| 2 | whatever3 |
+------+-----------+
3 rows in set (0.00 sec)
so, each id can appear 0, 1 or many times in table 2.
How do I do this select query?
I have tried various joins-queries but they exclude all id´s in table1 that does not exist in table2.
A LEFT OUTER JOIN enables you to join against a table where there may or may not be a matching record. If no matching record is there then the values from the columns of the other table for that row are NULL.
COUNT(field_name) will count all the non null values of field_name.
Hence you can do a LEFT OUTER JOIN and count the value of one of the fields:-
SELECT table1.id, table1.name, COUNT(table2.id) AS table2count
FROM table1
LEFT OUTER JOIN table2
ON table1.id = table2.id
GROUP BY table1.id, table1.name

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.

MySQL inner join among three tables syntax

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'