MySQL Select customers without an active order with JOIN - mysql

So, I am trying to select customers that are completely inactive with MySQL join. I have the following statement that selects all the customers with an active service order.
SELECT DISTINCT u.* FROM users u INNER JOIN orders o ON o.assigned=u.id AND o.status!=0
This works just fine. But now I am trying to select customers who previously had an order but the order became deactivated (o.status would equate to the value 0). I have the following statement (which is close) but it is returning customers who still have an active order, but have another order which was deactivated.
SELECT DISTINCT u.* FROM users u INNER JOIN orders o ON o.assigned=u.id AND o.status!=1
So in layman term, basically a customer can have multiple service orders. Every service being independent from one another, I want to select the customers who are COMPLETELY deactivated. For example:
Susan has 2 service orders, 1 which is activated and the other deactivated. Right now, Susan is being populated in the list of users who are deactivated and that is incorrect. Only the customers whose orders are completely deactivated.
Thank you!

SELECT u.*
FROM users u
LEFT
JOIN orders o
ON o.assigned=u.id
AND o.status!=0
WHERE o.assigned IS NULL;
or something like that

In order to account for this scenario, you need to do a WHERE clause that would include the opposite SELECT statement.
For example:
select distinct u.* from users u inner join orders o
on o.assigned=u.id and o.status!=1
where u.id != (select distinct s.id from users s inner join orders r
on r.assigned = s.id and r.status!=0 where s.id == u.id)

Related

Count function returning wrong value when joined

I am trying to find a count of actions completed along with company details for companies who have more than 10 users.
The code I am using is:
SELECT
c.company_name,
count(a.action) as actions,
count(u.user_id) as users
FROM
companies c
LEFT JOIN
auditing a on c.id=a.company_id
LEFT JOIN
users u on c.id=u.company_id
GROUP BY
c.id
HAVING
count(u.user_id)>10
LIMIT
10
When I run this it displays an incorrect number of actions.
For example, for the first company in the table it returns:
Company 1,111026,111026
whereas it should return:
Company 1,5093,22
I need to get back the number of actions and the number of users for all companies - how can I do this?
try putting in DISTINCT so that way you aren't counting duplicates
SELECT
c.company_name,
count(DISTINCT a.action) as actions,
count(DISTINCT u.user_id) as users
FROM
companies c
LEFT JOIN
auditing a on c.id=a.company_id
LEFT JOIN
users u on c.id=u.company_id
GROUP BY
c.id
HAVING
count(u.user_id)>10
LIMIT
10

MySQL Query phpmyadmin

I'm trying to make a SQL query that will search for user id and populate the query with the username.
These are my tables:
Table Names: 'users' and 'schedule'
This is how I want it to look like, where 'schedule' table now shows the username instead of the user's ID
This is the query you are looking for:
SELECT s.REFID, s.jobnum, s.customer, u1.username AS engineer, u2.username AS sales
FROM schedule s, users u1, users u2
WHERE s.engineer=u1.id
AND s.sales=u2.id
You need to reference the users table two separate times, since you are checking in one sub-query for the engineer's username, and then checking in a separate sub-query for the salesperson's username.
Here is a link to an SQLFiddle that shows the result of the query's execution. It matches up with what you were looking for. I hope this helps.
Following Query will give you the expected result:
SELECT
s.refid as refid,
s.jobnum as jobnum,
s.customer as customer,
u_engg.username as engineer,
u_sales.username as sales
FROM
user u_engg join schedule s on u.id = s.engineer join
user u_sale on u_sale.id = s.sales
SELECT s.refid, s.jobnum, s.customer, u.username engineer, u.username sales
FROM schedule s
LEFT OUTER JOIN users u
ON s.engineer = u.id AND s.sales = u.id
It looks like you need to reference the users table two times. One JOIN to get the engineer username, and a second JOIN to get the sales username.
Something like this:
-- return all rows from schedule, and lookup of username where available
SELECT s.REFID
, s.jobnum
, s.customer
, e.username AS engineer
, a.username AS sales
FROM schedule s
LEFT
JOIN users e
ON e.id = s.engineer
LEFT
JOIN users a
ON a.id = s.sales
Using a LEFT [OUTER] JOIN ensures that the rows from schedule will be returned when there isn't a matching row in the users table. For example, if you had a NULL in the sales column of a row in schedule, there wouldn't be a matching row in the users table. With an [INNER] JOIN, the row from schedule would not be returned. But the query above does return the row, but with a NULL for the username when matching rows are not found.
If the engineer and sales columns are defined as NOT NULL, and foreign keys are defined and enforced, then the LEFT keyword can be omitted from the query above. In the more general case, where foreign keys are not enforced (e.g. MyISAM) or not defined, or the columns are nullable, we'd generally want the LEFT keywords.
UPDATE
Removing the LEFT keywords from the query will produce a query equivalent to that in the answer from Alvin Lee, which implements INNER JOIN operations.
The query from Alvin Lee will EXCLUDE rows from schedule that have a value in the engineer or sales column that is NULL, or has a value that does not match a value found in the id column of the users table.
To identify if any rows in the schedule table are not being returned by the query using an INNER JOIN, you can run a query that does an anti-join pattern.
-- find rows in schedule that don't have matching row in users
SELECT s.REFID
, s.jobnum
, s.customer
, s.engineer
, s.sales
FROM schedule s
LEFT
JOIN users e
ON e.id = s.engineer
LEFT
JOIN users a
ON a.id = s.sales
WHERE a.id IS NULL
OR e.id IS NULL
try this:
select sc.REFID, sc.jobnum, sc.customer, us.username as engineer, us.username as sales
from schedules as sc
left join users as us on sc.engineer = us.ID and sc.sales = us.ID

MySQL Join table and count distinct users with no reference in another table

I am trying to count users that are NOT referenced in another table... Right now, I have something along the lines of this:
SELECT COUNT(DISTINCT u.id) FROM users u INNER JOIN orders o ON o.assigned!=u.id;
However, it's returning an invalid value. Any suggestions?
Thank you!
I would suggest using a LEFT JOIN between the two tables and filter the rows without a matching id in the orders table:
select count(u.id)
from users u
left join orders o
on o.assigned = u.id
where o.assigned is null
See SQL Fiddle with Demo
Use a left join and count the rows with no match:
SELECT COUNT(*)
FROM users u
LEFT JOIN orders o
ON o.assigned = u.id
WHERE o.assigned IS NULL
An alternative is to use a NOT IN check:
SELECT COUNT(*)
FROM users
WHERE id NOT IN (SELECT distinct(assigned) FROM orders)
However, in my experience the left join performs better (assuming appropriate indexes).
Simply use this query, assuming that the id is unique in users table:
select count(*) From Users as u where u.id not in (select assigned from orders)
an inner join explicitly looks for rows that match so that isn't the way to go if you are looking for non matched records
assuming that ORDERS.ASSIGNED is matched with USER.ID an outer join could return values from both and show when there aren't matches like so
select
u.id,
o.*
from users u
full outer join orders o
on o.assigned = u.id;
if you only want to know which USER.ID don't have an ORDERS record you could also INTERSECT or use NOT IN () eg
select u.id from users u where id not in (select o.assigned from orders.o);
SELECT COUNT(1) FROM users u
WHERE NOT EXISTS (SELECT * FROM orders o WHERE o.assigned=u.id);
Are you wanting a straight count (like you mentioned), or do you need values returned? This will give you the count; if you want other values, you should take one of the other approaches listed above.

MySQL using Group By to limit results

Okay, so I am trying to perform a query that has 4 tables,
users, events, event_roles, user_event_role.
The users can fill multiple roles. What i am trying to do is get a result that looks more like this:
User, event, Role(s)
So if user 'Bill' is associated with event 'Meeting' and 'Bill' Fills multiple roles instead of getting a result like this:
user event role
--------------------------
bill Meeting admin
bill Meeting director
how would I get my result to be like this
user event role role
----------------------------------
bill Meeting admin director
Here is a query that I'm trying to build off of.
Select *
FROM `users` u
LEFT JOIN `event_role` er ON u.user_id = er.user_id
LEFT JOIN `events` e ON er.event_id = e.event_id
The result you seek is not possible.
However there is something close:
SELECT
user,
event,
group_concat(role SEPARATOR ',') as roles
FROM
`users` u
LEFT JOIN `event_role` er
ON u.user_id = er.user_id
LEFT JOIN `events` e
ON er.event_id = e.event_id
GROUP BY u.user_id
which would yield:
user event roles
----------------------
bill Meeting admin,director
In either case you would need to adjust your logic to parse it correctly.
You cannot get such result, because you don't know how many roles there might be (i.e. columns count), but you can use GROUP_CONCAT that way:
SELECT *,
GROUP_CONCAT(event_roles.role SEPARATOR ',') as roles
FROM users
LEFT JOIN event_role USING(user_id)
LEFT JOIN events USING(user_id)
GROUP BY user_id
Using this query you will get all roles concatonated with ,. But be aware of limitation of GROUP_CONCAT, the default value is set to 1024 characters which might not be enough (see my.cnf).
Use Group_concat (http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html) like this.
To show that quickly, I'm using a database from the excellent MySQL intro book by Ben Forta (http://www.forta.com/books/0672327120/), no affiliation.
SELECT v.vend_id, GROUP_CONCAT(p.prod_id)
FROM products p
JOIN vendors v ON v.vend_id= p.vend_id
JOIN orderitems oi ON oi.prod_id = p.prod_id
GROUP BY v.vend_id;

MySQL Queries and 2 separate tables

So I have 2 tables in a MySQL database, one for "Users" and the other for "Orders", where each entry in Orders is an order placed by a User (Some users can have multiple orders, while some might not have any). I am working on reporting queries and one of the reports I want is a list of Users that have never placed any orders. I am still a bit of a beginner when it comes to MySQL queries, so I am not sure how to do this one. The query will be placed via PHP if that makes any difference.
Here are my columns in each table (simplified):
Users:
ID
Name
Orders:
OrderID
OrderName
CustomerID (corresponds to User.ID that placed the order)
Any help here would be great. Thanks!
Use a LEFT JOIN on Orders and check whether OrderId is null:
SELECT U.*
FROM
Users U
LEFT JOIN Orders O ON(U.ID = O.CustomerID)
WHERE
O.OrderId IS NULL
SQLFiddle
SELECT ID, Name
FROM users
WHERE ID NOT IN (SELECT DISTINCT customerID FROM Orders)
So basically you'are looking for orders that are not made by that user
Select * from Orders where CustomerID = 5 //5 is the id of the custumer
If you are doing a search by name
Select * from Orders LEFT JOIN Users on Users.ID Where Users.name ='Mark'
If no results, it mean that customer never ordered anything
Try
SELECT U.*
FROM Orders a
RIGHT JOIN Users b
ON b.ID = a.CustomerID
WHERE a.OrderId IS NULL