I need to insert a table with some values (eg: 'NDA' in this case). This seems to work well if I have just one value to be inserted. I have around a dozen of similar values, is there a was i can tweak this query to insert say { 'NDA', 'SDM', 'APM' } values. Was curious to know if it can be done without a stored procedure or copy pasting the same statements over and changing the values.
INSERT IGNORE INTO customer_feature (customer_id, feature)
SELECT c.id, 'NDA' FROM
customer as c
where c.edition = 'FREE_TRIAL';
Reference: mysql -> insert into tbl (select from another table) and some default values
Is this what you want?
INSERT IGNORE INTO customer_feature(customer_id, feature)
select c.id, f.feature
from customer c cross join
(select 'NDA' as feature union all select 'SDM' union all select 'APM'
) f
where c.edition = 'FREE_TRIAL';
Related
This question already has an answer here:
Select values from a list that are not in a table
(1 answer)
Closed 2 years ago.
I have a list of values:
('WEQ7EW', 'QWE7YB', 'FRERH4', 'FEY4B', .....)
and the dist table with a dist_name column.
and I need to create SQL query which would return values from the list which don't exist in the dist_name column.
Yo need to use left join. This requires creating a derived table with the values you care about. Here is typical syntax:
select v.val
from (values ('WEQ7EW'), ('QWE7YB'), ('FRERH4'), ('FEY4B')
) v(val) left join
t
on t.col = v.val
where t.col is null;
Not all databases support the values() table constructor but allow allow some method for creating a derived table. In MySQL, this looks like:
select v.val
from (select'WEQ7EW' as val union all
select 'QWE7YB' as val union all
select 'FRERH4' as val union all
select 'FEY4B' as val
) v(val) left join
t
on t.col = v.val
where t.col is null;
You would typically put this list of values in a derived table, and then use not exists. In MySQL:
select v.dist_name
from (
select 'WEQ7EW' as dist_name
union all select 'QWE7YB'
union all ...
) v
where not exists (select 1 from dist d where d.dist_name = v.dist_name)
Or if you are running a very recent version (8.0.19 or higher), you can use the VALUES ROW() syntax:
select v.dist_name
from (values row('WEQ7EW'), row('QWE7YB'), ...) v(dist_name)
where not exists (select 1 from dist d where d.dist_name = v.dist_name)
SELECT TRIM(TRAILING ',' FROM result) result
FROM ( SELECT #tmp:=REPLACE(#tmp, CONCAT(words.word, ','), '') result
FROM words, (SELECT #tmp:='WEQ7EW,QWE7YB,FRERH4,FEY4B,') arg
) perform
ORDER BY LENGTH(result) LIMIT 1;
fiddle
The list of values to be cleared from existing values is provided as CSV string with final comma and without spaces before/after commas ('WEQ7EW,QWE7YB,FRERH4,FEY4B,' in shown code).
If CSV contains duplicate values all of them will be removed whereas non-removed duplicates won't be compacted. The relative arrangement of the values will stay unchanged.
Remember that this query performs full table scan, so it is not applicable to huge tables because it will be slow.
What I am trying to do is to insert records from multiple tables into 1 table by joining. Here is what I have and I can't seem to get it to work. I get the following error #1136 - Column count doesn't match value count at row 1
INSERT INTO users(`name`, `email`,`location_id`, `department_id`)
VALUES('John Doe', 'jdoe#email.com', 1, 1)
INSERT INTO extensions(`ext`)
VALUES(98765)
INSERT INTO dids(`did`)
VALUES('1-800-555-5555')
INSERT INTO users_numbers(user_id,ext_id,did_id)
SELECT extensions.*, dids.*, users.*
FROM extensions tbl_ext, dids tbl_dids, users tbl_users, users_numbers usn
Inner Join users ON users.id=usn.user_id
Inner Join extensions ON extensions.id=usn.ext_id
Inner Join dids ON dids.id=usn.did_id
WHERE tbl_users.name = 'John Doe'
AND tbl_users.email = 'jdoe#email.com'
AND tbl_ext.ext = 98765
AND tbl_dids.did='401-559-9999';
The first 3 insert statements work. The error fires on the 4 insert when I try to join. Can anyone help.
Use LAST_INSERT_ID():
INSERT INTO users(`name`, `email`,`location_id`, `department_id`)
VALUES('John Doe', 'jdoe#email.com', 1, 1);
SET #user_id = LAST_INSERT_ID();
INSERT INTO extensions(`ext`)
VALUES(98765);
SET #ext_id = LAST_INSERT_ID();
INSERT INTO dids(`did`)
VALUES('1-800-555-5555');
SET #did_id = LAST_INSERT_ID();
INSERT INTO users_numbers(user_id,ext_id,did_id)
VALUES (#user_id,#ext_id,#did_id);
Instead of using user variables (#user_id,#ext_id,#did_id) you can also fetch the LAST_INSERT_ID in your application language.
There are two problems.
First, the SELECT list has to return only the columns that you want to insert into the table. The error is because you're returning tablename.* rather than specific columns.
Second, the SELECT query is very wrong. You have the tables that you're joining listed twice: first in the FROM clause and then again in the INNER JOIN clauses. You should only list them once (unless you're doing a self-JOIN, which is not needed here).
And you shouldn't be joining with users_numbers -- that's the table you're trying to add to, so it doesn't have the IDs for these rows yet.
What you want is a simple cross join between the rows from each of the source tables that match the values you're combining into the relation table.
INSERT INTO users_numbers(user_id,ext_id,did_id)
SELECT u.id, e.id, d.id
FROM users AS u
CROSS JOIN extensions AS e
CROSS JOIN dids AS d
WHERE u.name = 'John Doe'
AND u.email = 'jdoe#email.com'
AND e.ext = 98765
AND d.did='401-559-9999';
You need to be very specific about which columns you want from that SELECT. Right now you're grabbing everything from the three tables, that's too much.
Maybe you mean:
INSERT INTO users_numbers(user_id,ext_id,did_id)
SELECT users.id, extensions.id, dids.id
FROM ...
When composing complicated queries like this, run the SELECT subcomponent separately to ensure it produces the right data. I bet if you ran your version it'd show a bunch of columns.
I have table with Name|ValueA|ValueB.1|ValueB,2 where Name is not unique.
I want to extract the B.1 and B.2 values for the low and high A vales for each name.
Bob|1|200|205
Bob|2|500|625
Bob|7|450|850
Bob|3|644|125|
Ann|4|120|120
Ann|8|451|191
Ann|9|145|982
I want a new table with unique names with high and low ValueA, ValueB.1, ValueB.2
Bob|1|7|200|450|205|850
Ann|4|9|120|145|120|982
I remember there is some way to use min/max but am not sure how to set up the query to extract the new table.
INSERT newtable (Name, ValueA, ValueB.1, ValueB.2)
SELECT Name,MAX(ValueA),MIN(ValueA),MAX(ValueB.1),MIN(Value B.1),
MAX(ValueB.2),MIN(ValueB.2)
FROM oldtable GROUP BY Name
Should do the trick.
Assuming that values of A are distinct (at least within a name):
INSERT
INTO newtable
SELECT name, mmin.a, mmax.a, mmin.b1, mmin.b2, mmax.b1, mmax.b2
FROM (
SELECT name, MIN(a) mina, MAX(a) maxa
FROM mytable
GROUP BY
name
) md
JOIN mytable mmin
ON (mmin.name, mmin.a) = (md.name, md.mina)
JOIN mytable mmax
ON (mmin.name, mmin.a) = (md.name, md.maxa)
I have a table with a composite key composed of 2 columns, say Name and ID. I have some service that gets me the keys (name, id combination) of the rows to keep, the rest i need to delete. If it was with only 1 row , I could use
delete from table_name where name not in (list_of_valid_names)
but how do I make the query so that I can say something like
name not in (valid_names) and id not in(valid_ids)
// this wont work since they separately dont identity a unique record or will it?
Use mysql's special "multiple value" in syntax:
delete from table_name
where (name, id) not in (select name, id from some_table where some_condition);
If your list is a literal list, you can still use this approach:
delete from table_name
where (name, id) not in (select 'john', 1 union select 'sally', 2);
Actually, no I retract my comment about needing special juice or being stuck with (AND OR'ing all your options).
Since you have a list of values of what you want to retain, dump that into a temporary table. Then do a delete against the base table for what does not exist in the temporary table (left outer join). I suck at mysql syntax or I'd cobble together your query. Psuedocode is approximate
DELETE
B
FROM
BASE B
LEFT OUTER JOIN
#RETAIN R
ON R.key1 = B.key1
AND R.key2 = B.key
WHERE
R.key1 IS NULL
The NOT EXISTS version:
DELETE
b
FROM
BaseTable b
WHERE
NOT EXISTS
( SELECT
*
FROM
RetainTable r
WHERE
(r.key1, r.key2) = (b.key1, b.key2)
)
Is there a way to update multiple rows with different values for each row using a single SQL query? I have to update one colum in many rows with different data. Using individual update queries for each row seems excessive so if it's possible I would like to consolidate this process into a single SQL statement or at least reduce the number of queries required.
I am using PHP with the Zend framework and MySql.
Create a temporary table and fill it with:
CREATE TEMPORARY TABLE temptable (id INTEGER, VALUE VARCHAR(200))
INSERT
INTO temptable
VALUES
('1', 'val1'),
('2', 'val2'),
('3', 'val3'),
('4', 'val4')
Then issue:
UPDATE
mytable m, temptable t
SET m.value = t.value
WHERE m.id = t.id
Don't know about MySQL specifically, but to update multiple rows based on a SELECT, or a UNION of multiple SELECTs, I would do
UPDATE U
SET MyColumn = T.OtherColumn
FROM MyUpdateTable AS U
JOIN
(
SELECT [OtherColumn] = OtherColumn1
FROM MyOtherTable1
WHERE ...
UNION
SELECT OtherColumn2
FROM MyOtherTable2
WHERE ...
) AS T
ON T.ID = U.ID
Update 10/28/2014, converted to work for MySQL:
UPDATE MyUpdateTable AS U
JOIN
(
SELECT [OtherColumn] = OtherColumn1
FROM MyOtherTable1
WHERE ...
UNION
SELECT OtherColumn2
FROM MyOtherTable2
WHERE ...
) AS T
ON T.ID = U.ID
SET MyColumn = T.OtherColumn
I know this works for SQL Server, so it's worth a try in MySQL.
update xtable
set a =
Case
when a = "a"
then z
when a = "b"
then y
End
where ...
You can construct the case statement based on your different rows.