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.
Related
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.
INSERT INTO (
SELECT student_info.Student_Name,scores.Final
FROM student_info
INNER JOIN scores ON scores.Student_id=student_info.Student_id
AND scores.Subject_id=1)
(Student_Name,Final) VALUES("a",1)
Something like this.....What i want to achieve is that i want to add a new row to the queried result which will display the average of the columns above it.
Use UNION to combine the results of two queries into a single result:
SELECT student_info.Student_Name,scores.Final
FROM student_info
INNER JOIN scores ON scores.Student_id=student_info.Student_id
AND scores.Subject_id=1
UNION
SELECT "a", AVG(scores.Final)
FROM student_info
INNER JOIN scores ON scores.Student_id=student_info.Student_id
AND scores.Subject_id=1
if you need an insert select you could use this way
INSERT INTO your_table_name (Student_Name,Final)
SELECT student_info.Student_Name,scores.Final
FROM student_info
INNER JOIN scores ON scores.Student_id=student_info.Student_id
AND scores.Subject_id=1
and eventually if need a added row you can add an union clause with the literal value to your select
INSERT INTO your_table_name (Student_Name,Final)
SELECT student_info.Student_Name,scores.Final
FROM student_info
INNER JOIN scores ON scores.Student_id=student_info.Student_id
AND scores.Subject_id=1
union all
select "a", 1
from dual;
I have a query to insert some records using multiple Select statements
My query is as follows
INSERT INTO tbl_StreetMaster
(
StreetName,
CityID,
StartPoint,
EndPoint,
StoreID,
IsActive,
CreationDate,
CreatedBy
)
SELECT
(SELECT a.StreetName,CAST(a.CityName AS INT),a.EndPointFrom,a.EndPointTo
FROM #TempRecords a
WHERE NOT EXISTS
(SELECT b.StreetID,b.StreetName FROM tbl_StreetMaster b
WHERE a.StreetName=b.StreetName and a.EndPointFrom=b.StartPoint and
a.EndPointTo=b.EndPoint and CAST(a.CityName AS INT)=b.CityID and b.IsActive=1
))
,
(SELECT a.StoreID FROM tbl_StoreGridMapping a
inner join tbl_GridMaster b on a.GridID=b.GridID
inner join #TempRecords c on b.GridCode=c.GridCode1
WHERE NOT EXISTS
(SELECT b.StreetID,b.StreetName FROM tbl_StreetMaster b
WHERE c.StreetName=b.StreetName and c.EndPointFrom=b.StartPoint and
c.EndPointTo=b.EndPoint and CAST(c.CityName AS INT)=b.CityID and b.IsActive=1))
,
1,GETDATE(),100
Even though I have right number of columns in my Select it gives me error all the time
The select list for the INSERT statement contains fewer items
than the insert list. The number of SELECT values must match the number of INSERT
columns.
Can any one help out with this.
You can't return multiple columns from a subselect (so the system is probably assuming one column from each subselect and counting five columns total, and not getting far enough to tell you that the subselects can only return 1 value.
I'm not clear why you haven't written it as a single query anyway:
INSERT INTO tbl_StreetMaster
(
StreetName,
CityID,
StartPoint,
EndPoint,
StoreID,
IsActive,
CreationDate,
CreatedBy
)
SELECT
c.StreetName,CAST(c.CityName AS INT),c.EndPointFrom,c.EndPointTo,
a.StoreID, 1,GETDATE(),100
FROM tbl_StoreGridMapping a
inner join tbl_GridMaster b on a.GridID=b.GridID
inner join #TempRecords c on b.GridCode=c.GridCode1
WHERE NOT EXISTS
(SELECT b.StreetID,b.StreetName FROM tbl_StreetMaster b
WHERE c.StreetName=b.StreetName and c.EndPointFrom=b.StartPoint and
c.EndPointTo=b.EndPoint and CAST(c.CityName AS INT)=b.CityID and b.IsActive=1)
Unless the mapping through tbl_GridMaster and tbl_StoreGridMapping may not exist (and you want a null for StoreID, in which case you might want to replace the inner joins with right joins.
I'd also query the wisdom (somewhere along the line) of casting a column called CityName to an INT. Something's broken there (in naming, if nothing else).
You can do it if you put a union bewteen selects
like this:
INSERT INTO table(elem1,elem2,elem3) SELECT elem1,elem2,elem3 from table1 union select elem1,elem2,elem3 from table2 union select elem1,elem2,elem3 from table3
I have an existing documents table and a new permissions table. I want to create a script that will give all permissions to all of the existing documents. The documents_permissions table will need the document_id and permission_id (1,2,3). So for each document I will need to insert 3 rows. This is where I am at atm:
INSERT INTO `documents_permissions` (`document_id`, `permission_id`)
SELECT `id`, '1' FROM `documents`
but I'd need to repeat that for each permission. What is the best way to do this?
try this:
USe CROSS JOIN
INSERT INTO `documents_permissions` (`document_id`, `permission_id`)
select `id`,a.permissions
from(
select 1 as permissions union all
select 2 union all
select 3 )a
cross join
`documents` d
INSERT INTO `documents_permissions` (`document_id`, `permission_id`)
select id, pid from `documents`
cross join (select 1 as pid union select 2 union select 3)X
Is there a way to write a single query to check if a set of rows matches a set of values? I have one row per set of values that I need to match and I'd like to know if all rows are matched or not. I could perform this via multiple queries such as:
select * from tableName where (value1, value2) = ('someValue1', 'someValue2')
select * from tableName where (value1, value2) = ('someOtherValue1', 'someOtherValue2')
...and so on, up to an arbitrary number of queries. How could this sort of thing be re-written as a single query where the query returns ONLY if all values are matched?
You could try something like:
select t.*
from tableName t
join (select 'someValue1' value1, 'someValue2' value2 union all
select 'someOtherValue1', 'someOtherValue2') v
on t.value1 = v.value1 and t.value2 = v.value2
where 2=
(select count(distinct concat(v1.value1, v1.value2))
from (select 'someValue1' value1, 'someValue2' value2 union all
select 'someOtherValue1', 'someOtherValue2') v1
join tableName t1
on t1.value1 = v1.value1 and t1.value2 = v1.value2)
If you have a large number of value pairs that you want to check, it may be easier to insert them into a temporary table and use the temporary table in the above query, instead of two separate hard-coded virtual tables.
What about:
SELECT *
FROM tableName
WHERE value1 IN ('someValue1', 'someOtherValue1') AND
value2 IN ('someValue2', 'someOtherValue2')
Match if exactly two records found
Select students who got q13 wrong and Q14 right
SELECT qa.StudentID FROM questionAnswer qa, Student s
WHERE qa.StudentID=s.StudentID AND
((QuestionID=13 AND Pass=0) OR (QuestionID=14 AND Pass=1))
GROUP BY qa.StudentID
HAVING COUNT(*)=2;
The Where clause matches any records where q14 is correct and q13 is incorrect
We then group by the StudentID
The having requires there to be two records