I have a table of users:
UserID | User
1 Martin
2 Lilian
3 Oliver
Now I have another table:
dataID | UserID | key | value
Now what I need to do is:
Select certain users from the user-table and insert several recrods in the data-table:
I need to combine these two querys:
INSERT INTO `data` (`UserID`, `key`, `value`)
VALUES (HERE_ID_OF_USER, 'someKey', 10),
VALUES (HERE_ID_OF_USER, 'otherKey', 20)
SELECT `UserID` FROM `users` WHERE ...
Not sure I fully understand what you want to do, but I'll assume you want this:
INSERT INTO data (UserID,key,value) SELECT UserID,'somekey',10 FROM users WHERE ...
INSERT INTO data (UserID,key,value) SELECT UserID,'otherkey',20 FROM users WHERE ...
If that's not what you want, you'll need to be a bit more explicit...
Update
If you already have the data you want to insert for each user in a table, you can use:
INSERT INTO data (UserID,key,value)
SELECT u.UserID,dd.key,dd.value FROM users u,default_data dd WHERE ...
If you don't (and don't want to store it in a table), you can use;
INSERT INTO data (UserID,key,value)
SELECT UserID,'some key',10 FROM users WHERE ...
UNION ALL
SELECT UserID,'other key',20 FROM users WHERE ...
or (to avoid the repetition of the WHERE clause):
INSERT INTO data (UserId,key,value)
SELECT u.UserID,dd.key,dd.value
FROM users u,
(
SELECT 'some key' AS key,10 AS data
UNION ALL
SELECT 'other key',20
) dd
WHERE ...
There are probably more ways to do it.
Build your select query to fetch data from 2 table based on User ID join. Then insert the result set into the desired table.
INSERT INTO DATA (SELECT A.USER_ID, B.KEY, B.VALUE FROM USERS A, SECOND_TABLE B WHERE A.USER_ID = B.USER_ID AND A.USER_ID IN (.....))
Related
I have tables users (id, email), permissions (id, description) and users_permissions (user_id, permission_id, created) with many to many relation.
I need to select user with some email and assign to him all permissions from table permissions, which he does not have.
Now I am trying to assign at least all permissions, but I am getting error
Subquery returns more than 1 row
My query:
insert into `users_permissions` (`user_id`, `permission_id`, `created`)
select
(select `id` from `users` where `email` = 'user-abuser#gmail.com') as `user_id`,
(select `id` from `permissions`) as `permission_id`,
now() as `created`;
If a subquery (inside SELECT) returns more than one row, MySQL does not like it.
Another way to achieve your requirement is using CROSS JOIN between Derived Tables (subquery in the FROM clause):
INSERT INTO `users_permissions` (`user_id`, `permission_id`, `created`)
SELECT
u.id,
p.id,
NOW()
FROM
users AS u
CROSS JOIN permissions AS p
WHERE u.email = 'user-abuser#gmail.com'
I want to insert three values or three rows for each user I have. I know I can use the following query
INSERT INTO subscriptions(id_account, subscription)
SELECT id_account, 'subscriptionVAlue' FROM unnest ('{123,456,789}'::int[]) id;
to insert one row for each id in the list.
but I want is something like this
INSERT INTO subscriptions (account_id, subscription, i18nkey)
VALUES (id, 'subscription1', 'translation1')
VALUES (id, 'subscription2', 'translation2')
VALUES (id, 'subscription3', 'translation3')
where id in (123,1234,410,4512);
This is such bad query I know, but I want similar kind of behavior. Is that possible?
You can use cross join:
INSERT INTO subscriptions (account_id, subscription, i18nkey)
SELECT a.account_id, subscription, i18nkey
FROM (SELECT 'subscription1' as subscription, 'translation1' as i18nkey UNION ALL
SELECT 'subscription2', 'translation2' UNION ALL
SELECT 'subscription3', 'translation3'
) x CROSS JOIN
(SELECT 123 as account_id UNION ALL SELECT 1234 UNION ALL
SELECT 410 UNION ALL SELECT 4512
) a;
unnest() is not MySQL syntax. You can also do something similar with unnest(). The above should work in almost any database, although you might need a FROM clause (such as FROM dual) for the subqueries.
I use this query to insert multiple rows into my table user.
insert into user
(select 'bbb', coalesce(max(subid),0)+1 from user where name = 'bbb')
union
(select 'ccc', coalesce(max(subid),0)+1 from user where name = 'ccc');
How can I achieve the same result in a single select query?
Not quite. The problem is what happens when the names are not in the table. You can do this:
insert into user(name, subid)
select n.name, coalesce(max(u.subid), 1)
from (select 'bbb' as name union all select 'ccc') n left join
user u
on u.name = n.name
group by u.name;
It still has a union (all) for constructing the names, but the calculation of subid is only expressed once.
When using insert it is a good idea to list the columns explicitly.
So I'll do my best to describe the query that I'm trying to build.
I have a table I'll call user_records that has some data (several rows) for a relational ID, say userId (from a table users). For each row, I need to duplicate each row for another user. I know I could run this:
INSERT INTO user_records (userId, column1, column2, ...)
SELECT 10 as userId, column1, column2...
FROM user_records
WHERE userId = 1
This will copy the existing rows for userId 1 to userId 10.
But I want to run this for all userIds that are active and don't already exists in this table. So I want to basically execute this query first:
SELECT userID
FROM users
WHERE users.active = 1
AND NOT EXISTS (
SELECT * FROM user_records
WHERE users.userId = user_records.userId)
Using JOINS or simply combining the 2 queries, can I run this query and replace the 10 in the former query so that it duplicates the rows for a series of userIds?
Thanks in advance!
One way is to create a CROSS JOIN:
insert into user_records (userId, column1)
select u.userId, ur.column1
from user_records ur
cross join users u
where ur.userId = 1
and u.active = 1
and u.userId not in (select userId from user_records);
SQL Fiddle Demo
This will insert new rows into user_records for each userId that doesn't exist in the table, copying the data from UserId 1.
I have a table that has training history that has been modified by many different users over the years. This has cause the same training record to be entered twice. I want to create a table that replicates the main table and insert all duplicate records.
What constitutes a duplicate record is if the employee_id, course_code, and completion_date all match.
I can create the duplicate table and I have a select statement that appears to pull duplicates, but it pulls only one of them and I need it to pull both (or more) of them. This is because one person may have entered the training record with a different course name but the id, code, and date are the same so it is a duplicate entry. So by pulling all the duplicates I can validate that that is the case.
Here is my SELECT statement:
SELECT *
FROM
training_table p1
JOIN
training_table p2 ON (
p1.employee_id = p2.employee_id
AND p1.course_code = p2.course_code
AND p1.completion.date = p2.completion_date)
GROUP BY p1.ssn;
The query runs and returns what appear to be unique rows. I would like all of the duplicates. And whenever I try to INSERT it into an identical table I get an error stating my column count doesn't match my value count.
Any help would be great.
This will select any duplicate rows for insertion into your new table.
SELECT p1.*
FROM training_table p1
JOIN
(SELECT employee_id, course_code, completion_date
FROM training_table
GROUP BY employee_id, course_code, completion_date
HAVING COUNT(*) > 1
) dups
ON p1.employee_id = dups.employee_id
AND p1.course_code = dups.course_code
AND p1.completion_date = dups.completion_date
;
Try to use CROSS JOIN (Cartesian Product Join) instead JOIN only. For insert try INSERT INTO TABLE (column1, column2, column3) SELECT column1, column2, column3 FROM TABLE; in same order.
Thanks for the help. I had discovered the answer shortly after I posted the question (even though I had looked for the answer for over an hour :) ) Here is what I used:
SELECT *
FROM training_table mto
WHERE EXISTS
(
SELECT 1
FROM training_table mti
WHERE mti.employee_id = mto.employee_ie
AND mti.course_code = mto.course_code
AND mti.completion_date = mto.completion_date
LIMIT 1, 1
)
I just added the INSERT statement and it worked.
Thanks.