I have a tbl, for example:
uniqueId | col1 | col2 | col3
u1 8
u2
u3 13 89
What I want is to insert into the first empty column (can make them null if that helps). In the given if I'll add to u1 the value 2 it will be inserted into col2. If I do it for u2, it will enter col1. and for u3 it will enter to u3. These three queries will do the trick but I would rather do it in one.
INSERT INTO tbl SET col1 = $toInsertVal WHERE uniqueId=u col1=''
INSERT INTO tbl SET col2 = $toInsertVal WHERE uniqueId=u col1<>'' AND col2=''
INSERT INTO tbl SET col3 = $toInsertVal WHERE uniqueId=u col1<>'' AND col2<>'' AND col3=''
insert into tbl set
col1 = case when col1 = '' then $toInsertVal else col1 end
, col2 = case when col2 = '' and col1 <> '' then $toInsertVal else col2 end
...
where uniqueid = u
I've ignored NULLs for the sake of simplicity. Basically you can use a CASE on each column, checking on the first empty column and setting its value to its current value if no change is required.
Related
In my database, I have a default table (named "mytable") that I download from the internet. The table has say 100 rows and 10 columns (fields).
I am changing some values in the table but I'm not deleting nor inserting any rows or columns.
Say, in the fifth row of the table, I change the value of field "Name" from "Fox" to "Bear".
Then I download the table again from the internet, and I add it to the database with a different name.
So now I have the tables "oldtable" (containing the default values) and "mytable", where only a field in one row is changed.
Now, I want to show to others what I changed in the database and to give them the SQL script that they can run so they apply the same changes. I can't give them my own "mytable" because they can't use it. They also have it and they changed some values in it, as they see fit. They don't want my table, they just want to apply the changes that I made, on top of the changes that they already made to the table.
So I can give them this file named "patch.sql":
connect myDatabase;
update mytable set name="Bear" where name like "Fox";
However, I would like to create such a "patch.sql" file automatically, so I don't have to remember what I have changed and write the script manually. A program can check the differences between the two tables and generate that SQL file automatically.
Is it possible to do that in MySQL console or with any other existing tool?
Update: the table has a primary key.
if You edit with colleagues different rows, script could be easy.
But if You think You can edit same rows, but different columns, it look like next:
You have 2 tables
table_1:
id, col1, col2, col3
1 10 50 1
2 10 60 9
3 12 50 3
4 12 60 4
5 11 70 5
table_2:
id, col1, col2, col3
1 20 50 1
2 30 60 2
3 12 60 3
4 12 60 5
5 15 77 22
and run this script:
SELECT CONCAT('UPDATE table_1 SET '
, CASE WHEN t1.col1 != t2.col1 THEN CONCAT(' col1 = ', t2.col1) ELSE '' END
, CASE WHEN t1.col1 != t2.col1 AND t1.col2 != t2.col2 THEN ', ' ELSE ''END
, CASE WHEN t1.col2 != t2.col2 THEN CONCAT(' col2 = ', t2.col2) ELSE '' END
, CASE WHEN t1.col3 != t2.col3 AND (t1.col2 != t2.col2 OR t1.col1 != t2.col1) THEN ', ' ELSE ''END
, CASE WHEN t1.col3 != t2.col3 THEN CONCAT(' col3 = ', t2.col3) ELSE '' END
, CONCAT(' WHERE id = ', t1.id)) as update_txt
FROM table_1 t1 JOIN table_2 t2 ON t1.id = t2.id WHERE t1.col1 != t2.col1 OR t1.col2 != t2.col2 OR t1.col3 != t2.col3
Your result will be:
UPDATE table_1 SET col1 = 20 WHERE id = 1
UPDATE table_1 SET col1 = 30, col3 = 2 WHERE id = 2
UPDATE table_1 SET col2 = 60 WHERE id = 3
UPDATE table_1 SET col3 = 5 WHERE id = 4
UPDATE table_1 SET col1 = 15, col2 = 77, col3 = 22 WHERE id = 5
Then You need just copy result column to text file and send to other parts.
This is work for UPDATE, if You plan INSERT / DELETE rows, script will be more complicated, but use the same logic
I am a newbie to SQL so need help and suggestion on one thing which i came across.
My table looks like this:
Col1 Col2 Col3 Col4
1 AA BB NULL
2 AA BB NULL
3 AA BB 1000
4 CC DD NULL
5 CC DD 2000
I want to update the NULL values of Col4 with respective value at Col4 where Col2 and col3 values are same.
Like in my first row Col4 is having NULL while in 3rd row Col4 has value (with same Col1 and Col2 value)
I just want to know is there any way that I can update the NULL with specific values.
update your_table t1
join
(
select col2, col3, max(col4) as col4
from your_table
group by col2, col3
) t2 on t1.col2 = t2.col2 and t1.col3 = t2.col3
set t1.col4 = t2.col4
where t1.col4 is null
You can do this using a join:
update table t join
(select col2, col3, max(col4) as col4
from table t
group by col2, col3
) tt
on t.col2 = tt.col2 and t.col3 = tt.col3
set t.col4 = tt.col4
where t.col4 is null;
Note: this chooses the maximum value of col4 assuming that multiple rows have values.
I'm trying to write a view which "rotates" a table's data from vertical to horizontal:
Uid Name Key Value
1 User1 data1 resultX
2 User1 data2 resultY
3 User1 data3 resultZ
4 User2 data1 resultX
5 User2 data3 resultZ
The resulting data set should look like this:
Name Val1 Val2 Val3
User1 resultX resultY resultZ
User2 resultX NULL resultZ
The tricky thing is that I also want to display empty value fields.
The only way I could more or less achieve this was with sub selects like this
(More or less means: This only works for data sets where a key=data1 is present):
SELECT
t1.name
, t1.value AS val1
, t2.value AS val2
, t3.value AS val3
FROM (
SELECT
name
, value
FROM
tableA
WHERE
key = 'data1'
) t1
LEFT JOIN (
SELECT
name
, value
FROM
tableA
WHERE
key = 'data2'
) t2
ON t1.name= t2.name
LEFT JOIN (
SELECT
name
, value
FROM
tableA
WHERE
key = 'data3'
) t3
ON t1.name= t3.name
;
Is there a better way to achieve this?
If its for known set of items like data1,data2 and data3 in your case, you can use the following technique
select
name,
max(case when `key` = 'data1' then value end) as val1,
max(case when `key` = 'data2' then value end) as val2,
max(case when `key` = 'data3' then value end) as val3
from tableA group by name ;
I have a two tables in my database, tableA and tableB.
tableA:
id | col1 | col2 | in_b
-----------------------
1 | "abc" | "efg" | false
2 | "foo" | "bar" | false
tableB:
id | col1 | col2
------------------
1 | "abc" | "bar"
I want to update the in_b column so that it is true if either col1 or col2's values matches a row in tableB. For example, both in_b flags would be true, because "abc" is in col1 of tableB and "bar" is in col2 of tableB. col1 and col2 are not unique.
What is the best way to update the in_b flag?
I think you want something along the lines of
UPDATE tableA
SET in_b = TRUE
WHERE EXISTS ( SELECT 1 FROM tableB
WHERE (tableB.col1 = tableA.col1 OR tableB.col2 = tableA.col2)
)
Based on your question there is no link between the IDs on both table and try to match both columns from tablea with tableb (col1, col2), just a full search for the values. So your update would be:
update tablea a inner join tableb b on ( (a.col1=b.col1 or a.col1=b.col2) or
(a.col2=b.col1 or a.col2=b.col2) )
set a.in_b = true;
See it here on fiddle: http://sqlfiddle.com/#!2/3b847/1
In my example I've added a row to the tablea which doesn't have any matches on tableb
i have a denormalized table, where i have to count the number of same values in other columns.
I'm using the InfiniDB Mysql Storage Engine.
This is my Table:
col1 | col2 | col3
------------------
A | B | B
A | B | C
A | A | A
This is what i expect:
col1Values | col2Values | col3Values
------------------------------------
1 | 2 | 2 -- Because B is in Col2 and Col3
1 | 1 | 1
3 | 3 | 3
Is there something like
-- function count_values(needle, haystack1, ...haystackN)
select count_values(col1, col1, col2, col3) as col1values -- col1 is needle
, count_values(col2, col1, col2, col3) as col2values -- col2 is needle
, count_values(col3, col1, col2, col3) as col3values -- col3 is needle
from table
or am i missing something simple that will do the trick? :-)
Thanks in advance
Roman
select
CASE WHEN col1 = col2 and col1=col3 THEN '3'
WHEN col1 = col2 or col1=col3 THEN '2'
WHEN col1 != col2 and col1!=col3 THEN '1'
ELSE '0' END AS col1_values,
CASE WHEN col2 = col1 and col2=col3 THEN '3'
WHEN col2 = col1 or col2=col3 THEN '2'
WHEN col2 != col1 and col2!=col3 THEN '1'
ELSE '0' END AS col2_values,
CASE WHEN col3 = col1 and col3=col2 THEN '3'
WHEN col3 = col1 or col3=col2 THEN '2'
WHEN col3 != col1 and col3!=col2 THEN '1'
ELSE '0' END AS col3_values
FROM table_name
fiddle demo
Assuming the table has got a key, you could:
Unpivot the table.
Join the unpivoted dataset back to the original.
For every column in the original, count matches against the unpivoted column.
Here's how the above could be implemented:
SELECT
COUNT(t.col1 = s.col OR NULL) AS col1Values,
COUNT(t.col2 = s.col OR NULL) AS col2Values,
COUNT(t.col3 = s.col OR NULL) AS col3Values
FROM atable t
INNER JOIN (
SELECT
t.id,
CASE colind
WHEN 1 THEN t.col1
WHEN 2 THEN t.col2
WHEN 3 THEN t.col3
END AS col
FROM atable t
CROSS JOIN (SELECT 1 AS colind UNION ALL SELECT 2 UNION ALL SELECT 3) x
) s ON t.id = s.id
GROUP BY t.id
;
The subquery uses a cross join to unpivot the table. The id column is a key column. The OR NULL bit is explained in this answer.
I have found a different, very very simple solution :-)
select if(col1=col1,1,0) + if(col2=col1,1,0) + if(col3=col1,1,0) as col1values -- col1 is needle
from table