MySql update value with multitalbe select - mysql

I need to write MySql script to automatically change member role in Redmine bugtracker every week or so. The problem is that I got user login and there is a really long way to get to the member role id (what you can figure out by hte nested select in find_in_set function).
I made this query, which displays actually what I want, but the table is not updated:
SELECT REPLACE (role_id, '6', '4') as role_id
FROM member_roles
WHERE FIND_IN_SET( member_roles.member_id , (
SELECT member_roles.member_id
FROM members,users,member_roles, roles
WHERE members.id=member_roles.member_id
AND members.user_id=users.id
AND member_roles.role_id=roles.id
AND users.login='user01'))
the result of this query is:
-----------
| role_id |
-----------
| 4 |
-----------
I do not know how to update table instead of just displaying the result of this query.
Any help will be appreciated.

You just need to put that query in the update clause, for example:
UPDATE member_roles SET YOUR_FIELD(S)_TO_UPDATE=VALUE(S)
WHERE role_id=(YOUR_SELECT_CLAUSE)
You can change the operator to IN in the where clause in case you have multiple results

I converted the whole thing to the multi-table syntax for UPDATE:
UPDATE member_roles
JOIN members ON members.id = member_roles.member_id
JOIN users ON members.user_id = users.id
JOIN roles ON member_roles.role_id=roles.id
SET member_roles.role_id = '4'
WHERE member_roles.role_id = '6'
AND users.login='user01'
Note that I've added the condition that role_id = '6' in order to allow for your REPLACE() statement - I'm not sure if you want that or not.
I hope I got all your conditions correct - you may want to test it like this first:
SELECT role_id
FROM member_roles
JOIN members ON members.id = member_roles.member_id
JOIN users ON members.user_id = users.id
JOIN roles ON member_roles.role_id=roles.id
WHERE member_roles.role_id = '6'
AND users.login='user01'
Check and make sure you are getting the same number of records that you were getting before.

try this:
UPDATE member_roles
set role_id='4'
WHERE FIND_IN_SET( member_roles.member_id , (
SELECT member_roles.member_id
FROM members,users,member_roles, roles
WHERE members.id=member_roles.member_id
AND members.user_id=users.id
AND member_roles.role_id=roles.id
AND users.login='user01'))

Related

The multi-part identifier could not be bound in a multiple condition where statement

I'm trying to add an additional WHERE condition with AND to my mySQL query but keep getting the error The multi-part identifier userR.externalSource could not be bound
I have the alias setup in my left join from my other table but still I get this error. Could someone explain me why this is happening. I found article but this does not seem to be the case. I think it's rather a formatting issue of my query.
This query just counts 2 different groups of users but they can't have an empty (NULL) field for the externalSource field from the dbo.AAA_users table.
SELECT SUM(A.ROLECOUNT) AS 'Advanced Users' ,
(SELECT SUM(A.ROLECOUNT)
FROM (
SELECT role.logicalName AS Role_name ,
COUNT(DISTINCT users.userId) AS RoleCount
FROM dbo.AAA_UserRoleResource AS users
LEFT JOIN dbo.AAA_Role AS role ON role.roleId = users.roleId
LEFT JOIN dbo.AAA_User AS userR ON userR.userId = users.userId
GROUP BY role.logicalName
) A
WHERE A.Role_name IN ('ROLE_VIEWER', 'ROLE_USER')
AND userR.externalSource is not NULL <-- issue here
) AS 'Basic user'
FROM(
SELECT role.logicalName AS Role_name ,
COUNT(DISTINCT users.userId) AS RoleCount
FROM dbo.AAA_UserRoleResource AS users
LEFT JOIN dbo.AAA_Role AS role ON role.roleId = users.roleId
LEFT JOIN dbo.AAA_User AS userR ON userR.userId = users.userId
GROUP BY role.logicalName
) A
WHERE A.Role_name IN ('ROLE_ADMIN');
Any help appreciated.
So i figured out why it was not working.
I was adding the additional WHERE condition outside of the parenthesis and because of this it did not find the identifier which is within the parenthesis.

Selecting multiple values from same column with a single Select query

So, I've got two tables: users and tasks;
users:
user_id username password first_name last_name isAdmin
tasks:
task_id name description assessment assigned_user_id fk creator_id fk created_on last_modified status
What I want to do is replace assigned_user_id and creator_id with first_name + last_name from users table. So I execute the following query:
SELECT `task_id`, `description`,`assessment`,
(SELECT CONCAT(`first_name`, ' ',`last_name`) WHERE `Tasks`.`assigned_user_id` = `Users`.`user_id`) AS assigned_user,
(SELECT CONCAT(`first_name`, ' ',`last_name`) WHERE `Tasks`.`creator_id`=`Users`.`user_id`) AS creator_user,
`created_on`,`last_modified`,`status`
FROM `Tasks`
LEFT JOIN `Users`
ON Tasks.assigned_user_id = Users.user_id
OR Tasks.creator_id = Users.user_id
WHERE task_id=2
The problem is that it returns 2 rows. One is with assigned_user_id null and filled creator_id and the other is the other way around:
task_id description assessment assigned_user creator_user created_on last_modified status
2 SHA SA PII LI 24 NULL Petyo Chuliuv 2016-07-22 2016-07-22 1
2 SHA SA PII LI 24 Gosho Toshov NULL 2016-07-22 2016-07-22 1
Question is: How to return a single row with assigned_user and creator_user filled and where I did wrong? Thanks in advance!
I tested this on SQL Server and reproduced the same issue as you so hopefully I can be of help.
When I did the test the two SELECT CONCAT statements were using the same user_id both times. So the issue seems that it is not checking for both ids at once but both ids at separate times. So if I were to use your example it first uses Petyo's id in both of the SELECT CONCAT statements (only filling the creator_user role so the other one becomes false) and then it uses Gosho's id in both of the SELECT CONCAT statements which also only fills one field (the assigned_user field) and making the other one null.
So what you need to do is JOIN the Users table again. One for the assigned, one for the create. Something like this...
SELECT `task_id`, `description`,`assessment`,
(SELECT CONCAT(`U1.first_name`, ' ',`U1.last_name`)) AS assigned_user,
(SELECT CONCAT(`U2.first_name`, ' ',`U2.last_name`)) AS creator_user,
`created_on`,`last_modified`,`status`
FROM `Tasks`
LEFT JOIN `Users` U1
ON Tasks.assigned_user_id = U1.user_id
LEFT JOIN `Users` U2
ON Tasks.creator_id = U2.user_id
WHERE task_id=2
Before you had an OR. It does not look at one side, look for the id, then look at the other one, look for the id, then use it at once. It is exactly that. If the current user_id it is looking for happens to be one of those two then it uses that single user_id.
You need to join to your users table twice and alias them...
Somethin like...
SELECT `task_id`, `description`,`assessment`,
(SELECT CONCAT(`assignedUsers.first_name`, ' ',`assignedUsers.last_name`) AS assigned_user,
(SELECT CONCAT(`createdUsers.first_name`, ' ',`createdUsers.last_name`) AS creator_user,
`created_on`,`last_modified`,`status`
FROM `Tasks`
LEFT JOIN `Users` assignedUsers ON Tasks.assigned_user_id = assignedUsers .user_id
LEFT JOIN `Users` createdUsers ON Tasks.creator_id = createdUsers .user_id
WHERE task_id=2
Since you have two foreign keys and you want to fetch the corresponding data you just have to INNER JOIN the users table twice.
You used LEFT JOIN which will fetch all the data from the first table,in your case tasks, even if no match is found in the second table (in your case this did not made any difference but in cases where an id is not set or the user does not exist anymore maybe this is a problem that is up to you to decide...) and you also used OR in the JOIN conditions which resulted in duplicate tasks in the results.
So you must INNER JOIN twice.One time to get the assigned user and one to get the creator.
Havent tested but this should work :
SELECT t.`task_id`, t.`description`,t.`assessment`,
CONCAT(u1.`firstname`,' ',u1.`lastname`) as creator,
CONCAT(u2.`firstname`,' ',u2.`lastname`) as assigned_user,
t.`created_on`,t.`last_modified`,t.`status`
FROM `tasks` t
INNER JOIN `users` u1 ON t.creator_id=u1.id
INNER JOIN `users` u2 ON t.assigned_user_id=u2.id
WHERE t.`task_id`=2
Thank you all guys but I fixed it by doing:
SELECT `task_id`, `description`,`assessment`,
(SELECT CONCAT(`first_name`, ' ', `last_name`)
FROM `Users`
WHERE `Tasks`.`assigned_user_id` = `Users`.`user_id`) AS assigned_user,
(SELECT CONCAT(`first_name`, ' ', `last_name`)
FROM `Users`
WHERE `Tasks`.`creator_id`=`Users`.`user_id`) AS creator_user,
`created_on`,`last_modified`,`status`
FROM `Tasks`
WHERE task_id=3
I just added FROM Users and WHERE clauses in each inner SELECT,
so I didn't have to do any joins... As always it was way more simple than I thought. Thanks again, much appreciated!

MySQL - Operand should contain 1 column(s)

While working on a system I'm creating, I attempted to use the following query in my project:
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
FROM topics
LEFT OUTER JOIN posts ON posts.topic_id = topics.id
WHERE topics.cat_id = :cat
GROUP BY topics.id
":cat" is bound by my PHP code as I'm using PDO. 2 is a valid value for ":cat".
That query though gives me an error: "#1241 - Operand should contain 1 column(s)"
What stumps me is that I would think that this query would work no problem. Selecting columns, then selecting two more from another table, and continuing on from there. I just can't figure out what the problem is.
Is there a simple fix to this, or another way to write my query?
Your subquery is selecting two columns, while you are using it to project one column (as part of the outer SELECT clause). You can only select one column from such a query in this context.
Consider joining to the users table instead; this will give you more flexibility when selecting what columns you want from users.
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
COUNT( posts.solved_post ) AS solved_post,
users.username AS posted_by,
users.id AS posted_by_id
FROM topics
LEFT OUTER JOIN posts ON posts.topic_id = topics.id
LEFT OUTER JOIN users ON users.id = posts.posted_by
WHERE topics.cat_id = :cat
GROUP BY topics.id
In my case, the problem was that I sorrounded my columns selection with parenthesis by mistake:
SELECT (p.column1, p.column2, p.column3) FROM table1 p WHERE p.column1 = 1;
And has to be:
SELECT p.column1, p.column2, p.column3 FROM table1 p WHERE p.column1 = 1;
Sounds silly, but it was causing this error and it took some time to figure it out.
This error can also occur if you accidentally use commas instead of AND in the ON clause of a JOIN:
JOIN joined_table ON (joined_table.column = table.column, joined_table.column2 = table.column2)
^
should be AND, not a comma
This error can also occur if you accidentally use = instead of IN in the WHERE clause:
FOR EXAMPLE:
WHERE product_id = (1,2,3);
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
Well, you can’t get multiple columns from one subquery like that. Luckily, the second column is already posts.posted_by! So:
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
posts.posted_by
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by_username
FROM users
WHERE users.id = posts.posted_by)
...
I got this error while executing a MySQL script in an Intellij console, because of adding brackets in the wrong place:
WRONG:
SELECT user.id
FROM user
WHERE id IN (:ids); # Do not put brackets around list argument
RIGHT:
SELECT user.id
FROM user
WHERE id IN :ids; # No brackets is correct
This error can also occur if you accidentally miss if function name.
for example:
set v_filter_value = 100;
select
f_id,
f_sale_value
from
t_seller
where
f_id = 5
and (v_filter_value <> 0, f_sale_value = v_filter_value, true);
Got this problem when I missed putting if in the if function!
Another place this error can happen in is assigning a value that has a comma outside of a string. For example:
SET totalvalue = (IFNULL(i.subtotal,0) + IFNULL(i.tax,0),0)
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
Here you using sub-query but this sub-query must return only one column.
Separate it otherwise it will shows error.
I also have the same issue in making a company database.
this is the code
SELECT FNAME,DNO FROM EMP
WHERE SALARY IN (SELECT MAX(SALARY), DNO
FROM EMP GROUP BY DNO);

Updating a Field of record if it is found to be a duplicate

I have the following Mysql select that returns all the duplicate email addresses in my table.
SELECT users.FirstName, `Surname`, users.email1
FROM users
INNER JOIN (
SELECT email1
FROM users
GROUP BY email1
HAVING count(email1) > 1) dup ON users.email1 = dup.email1
ORDER BY users.email1
This works great, what I wish to do now is update a field called users.DupEmail with "YES" but I am unsure how to do this. I have tried putting an update line to replace the select, but I am clearly getting it wrong as I am back here asking for help.
Can anyone help please?
You can just use the multiple-table UPDATE syntax with a self-join:
UPDATE users AS u1
JOIN users AS u2 USING (email1)
SET u1.DupEmail = 'YES'
WHERE NOT u1.id = u2.id; -- use your primary key here
The following script must solve your problem -- be safe and use the SELECT to test results before aplying the update:
-- SELECT FirstName, Surname, email1
-- FROM users
UPDATE users
SET DupEmail = 1
WHERE u0.email1 IN (
SELECT u1.email1
FROM users u1
GROUP BY u1.email1
HAVING COUNT(*) > 1
)

help with this query It shows repeated records and It is not working?

I am trying to write a sql statement to retrieve all the messages with user_id_user = '3' and status = '2' but I get repeated records I dont know why, I am stuck with it
My tables are this
message
id_message title content date user_id_user status
-------------------------------------------------------------
user
id_user name
----------------
message_has_user
message_id_message user_id_user
----------------------------------
my mysql query but I get repeated records I dont know why, I am reading tutorial also any help really appreciated
SELECT
message.title,
message.content,
message.date,
message.id_message,
message_has_usuario.user_id_user,
message.status,
user.name
FROM
message ,
message_has_usuario
INNER JOIN user ON message_has_usuario.user_id_user = '3'
WHERE
message.status = '2'
You're getting a Cartesian product because you're not joining all your tables accurately.
You're joining USER and MESSGAE_HAS_USERIO but you're not doing any joins on MESSAGE
Quick Example _ I assume those relationships are correct.
SELECT *
FROM Message M
INNER JOIN Message_Has_User MAU on M.MessageID = MAU.MessageID
INNER JOIN User U ON MAU.UserID = U.UserID AND U.UserID = M.User_Id_User
WHERE MAU.userID = '3'
AND M.Status = '2'
I neither endorse or will admit that I used a Select *. Darn it all to heck that I even wrote it. /hides
Try this:
...
FROM message
JOIN message_has_usuario
on message_has_usuario.message_has_usuario = message.message_has_usuario
...
select message.*
from message, user
where user.id = 3
and user.id = message.user_id_user
and message.status = 2
Your not using INNER JOIN correctly. This should work for you!! Also what is the point of the message_has_user table? I looks redundant in this case since you can store the user_id directly on the message table. A user can have many messages, ie. One-To-Many.