I need to display the name of the user and their department who has raised the maximum number of queries. I wrote the following query by joining 5 tables; user, query, profile, degree, and department.
The problem is in the result the alias is not being used for the column names. For both the columns it appears as just name
select user.name 'USER_NAME',department.name 'DEPT_NAME'
from user
inner join query on (query.user_id=user.id)
inner join profile on (user.profile_id=profile.id)
inner join degree on (profile.degree_id=degree.id)
inner join department on (degree.department_id=department.id)
group by user.name
order by count(query.id) desc
limit 1
Use 'as' keyword in order to use alias name in mysql and also remove single quotes.
select user.name as USER_NAME from user;
The following syntax work perfectly for me :
select U.name AS "USER_NAME", D.name AS "DEPT_NAME"
from user U
inner join query Q on (Q.user_id=U.id)
inner join profile P on (U.profile_id=P.id)
inner join degree C on (P.degree_id=C.id)
inner join department D on (C.department_id=D.id)
group by U.name
order by count(Q.id) desc
limit 1;
Sometimes, Mysql prefer you pout an alias on your column when you use some JOIN.
Try it this way;
select thisuser.name 'USER_NAME',department.name 'DEPT_NAME'
from user as thisuser
inner join query on (query.user_id=thisuser.id)
inner join profile on (thisuser.profile_id=profile.id)
inner join degree on (profile.degree_id=degree.id)
inner join department on (degree.department_id=department.id)
group by thisuser.name
order by count(query.id) desc
limit 1
but this is not a good practice when constructing a query;
it looks like this
select thisuser.name,thisdept.name from
(select name,user_id from user) as thisuser
inner join
(select name,user_id from department) as thisdept
on thisuser.user_id = thisdept.user_id
Simply remove the quotes from your query and it will work, but you could use the keyword AS to make it clear that you're using an alias.
I would also use lower case aliases in order to avoid confusion with keywords, and also use uppercase for keywords;
SELECT user.name AS user_name, department.name AS dept_name
...
Related
I have three tables in MySQL. Staff with fields id, name, surname, telephone, adress, id_work.
Work with fields id, name.
Absence with fields id, name, id_staff.
I have the following query
SELECT COUNT(*)
FROM staff s, work w, absence a
WHERE s.id=a.id_staff
AND s.id_work=w.id
AND w.name='sales manager'
AND a.name='disease'.
The aforementioned query returns the staff which have the post of sales and are ill.
Is there is a way to return the inverse result namely the staff which have the post of sales but are not ill?
I change my where clause with where not exists but did not work
Never use commas in the FROM clause. Always use proper, explicit JOIN syntax.
One method of solving this uses LEFT JOIN:
SELECT COUNT(*)
FROM staff s JOIN
work w
s.id_work = w.id LEFT JOIN
absence a
ON s.id = a.id_staff AND a.name = 'disease'
WHERE w.name='sales manager' AND a.id_staff IS NULL;
You should also avoid 'CROSS JOIN' except where it is necessary :
SELECT COUNT(*)
FROM staff s
INNER JOIN work w ON s.id_work = w.id
LEFT JOIN absence a ON s.id = a.id_staff
WHERE w.name='sales manager'
AND a.name = 'disease'
AND a.id_staff IS NULL;
So I have the below database structure
TABLES ------- Columns
person: id, name, salary, address
group: id, name
person_group: person_id, groud_id
So here is my query which is used to get all persons along with the groups they are associated with
SELECT p.id, p.name,
group_concat(g.name) as groups
FROM person_group pg, group g, person p
WHERE pg.group_id = g.id AND pg.novel_id = n.id
GROUP BY ng.person_id
So this query gives me data like
id name groups
2345 John Admin, SuperAdmin, RedHat
But the problem is: if that person doesn't belong to any group, the query doesn't return that person!
Any would be appreciated!
Never use commas in the FROM clause. Always use proper, explicit JOIN syntax.
That is exactly your problem here. When you are writing more than one table in the FROM clause, you should be thinking "what type of JOIN do I need". If you had that thought, you would immediate realize that you need an outer join to do what you want:
SELECT p.id, p.name, group_concat(g.name) as groups
FROM person p LEFT JOIN
person_group pg
ON pg.person_id = p.id LEFT JOIN
group g
ON pg.group_id = g.id
GROUP BY p.id, p.name;
If you don't know what an outer join is, then that is all the more reason to use the proper, explicit syntax, so you can learn.
Consider this query
SELECT users.id,
users.name
FROM users
LEFT JOIN suppliers
ON users.id = suppliers.id
AND users.hall = suppliers.hall
WHERE USER.payment > 300
In this how will the change of order in the conditions of join matter ( i.e. id second and hall first)?
The order of the Join conditions has no effect on the result since they represent a boolean expression which is analysed in whole.
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.
The following query does what I want. It returns all the resuls in the users table and then if there is a match in the details tble, returns the relevant data
users
id|username
details
id|userid|firstname|lastname
$sql = "SELECT u.*, d.*
FROM `users` u
LEFT JOIN `details` d on
u.id = d.userid
ORDER BY $strorder";
However, when I try to join an additonal table where I want to do the same thing--return all the results of the users table and if there is a match in the third table, return the relevant data (total followers of this user)--it only returns one record.
3rd table
follow
id|followerid|followedid
$sql = "SELECT u.*, d.*, COUNT(f.id)
FROM `users` u
LEFT JOIN `details` d on
u.id = d.userid
LEFT JOIN `follow` f on
u.id = f.followedid
ORDER BY $strorder";
Can anyone see what I am doing wrong? Thanks in advance for any suggestions.
Many thanks.
Try to avoid * to select fields, it will be clearer to group your datas (even if mysql is quite permissive with groupings).
When you have an aggregate function (like COUNT, SUM), the other "non aggregated" requested fields should be in a GROUP BY clause.
Mysql don't force you to GROUP BY all the fields, but... I think it's quite a good habit to be "as ANSI as possible" (usefull when you use another DBMS)
SELECT u.id, u.username, d.firstname, d.lastname, count(*) as numberfollowers
FROM user u
LEFT JOIN details d on u.id = d.userid
LEFT JOIN follow f on u.id = f.followedid
GROUP BY u.id, u.username, d.firstname, d.lastname --or just GROUP BY u.id with Mysql
ORDER BY count(*) desc
COUNT being an aggregate function, when selected with other columns, requires you to group your results by those other columns in the select list.
You should rewrite your query with columns that you want to select from users and details and group by those columns.