I have following 2 tables t1, t2
CREATE TABLE t1 (
id INT PRIMARY KEY
);
CREATE TABLE t2 (
id INT PRIMARY KEY
);
INSERT INTO t1 VALUES (1),(2),(3);
INSERT INTO t2 VALUES (2),(3),(4);
I am running
select * from t1 left join t2 using(id);
Result:
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
+----+
On running script:
select t1.id, t2.id from t1 left join t2 using(id);
Result:
+----+------+
| id | id |
+----+------+
| 1 | NULL |
| 2 | 2 |
| 3 | 3 |
+----+------+
select * is supposed to return all the columns, so, why I am not getting 2 rows when I am using select *?
Note: I am using Mysql
as doc says:
Natural joins and joins with USING, including outer join variants, are processed according to the SQL:2003 standard:
Redundant columns of a NATURAL join do not appear. Consider this set of statements:
CREATE TABLE t1 (i INT, j INT);
CREATE TABLE t2 (k INT, j INT);
INSERT INTO t1 VALUES(1, 1);
INSERT INTO t2 VALUES(1, 1);
SELECT * FROM t1 JOIN t2 USING (j);
column j is named in the USING clause and should appear only once in the output, not twice.
This is the normal behavior of the USING clause. Here's a quote from MySQL documentation:
Similarly, in the second SELECT statement, column j is named in the USING clause and should appear only once in the output, not twice.
(JOIN syntax)
And here's from Wikipedia:
[...] any columns mentioned in the USING list will appear only once, with an unqualified name, rather than once for each table in the join.
(JOIN (SQL)
Related
I have a table like this in MYSQL:
ID | NAME | VALUE |
----------------------------
1 | Bob | 1 |
2 | Bob | 2 |
3 | Jack | 5 |
4 | Jack | 8 |
5 | Jack | 10 |
and I'm trying to update the VALUE column to the highest value of rows with same NAME. So the result should be:
ID | NAME | VALUE |
----------------------------
1 | Bob | 2 |
2 | Bob | 2 |
3 | Jack | 10 |
4 | Jack | 10 |
5 | Jack | 10 |
I managed to get the max value like this:
SELECT MAX(Value) max FROM `table` GROUP BY Name having count(*) >1 AND MAX(Value) != MIN(Value)
But can't figure out how to put it in my update
Update table set Value = (SELECT MAX(Value) max FROM `table` GROUP BY Name having count(*) >1 AND MAX(Value) != MIN(Value))
Doesn't work. I'd appreciate any help.
This is easier than other answers are making it.
UPDATE MyTable AS t1 INNER JOIN MyTable AS t2 USING (Name)
SET Value = GREATEST(t1.Value, t2.Value);
You don't have to find the largest value. You just have to join each row to the set of rows with the same name, and set the Value to the greater Value of the two joined rows. This is a no-op on some rows, but it will apply to every row in turn.
http://sqlfiddle.com/#!9/f79a3/1
UPDATE t1
INNER JOIN (SELECT name, MAX(`value`) max_value
FROM t1 GROUP BY name) t2
ON t1.name = t2.name
SET t1.value = t2.max_value;
Create a temporary table consisting of ID NAME and MAX VALUE as follows:
CREATE TEMP TABLE TABLE1 AS
(SELECT NAME,MAX(Value) value FROM `table` GROUP BY Name having count(*) >1
AND MAX(Value) != MIN(Value)
);
Use this temporary table to do your update as follows:
UPDATE
Table_A
SET
Table_A.value = Table_B.value
FROM
`table` AS Table_A
INNER JOIN TABLE1 AS Table_B
ON Table_A.NAME = Table_B.NAME
Also this code is somewhat of an approximation as i am not familiar with mysql but i am familiar with sql.
Let me know if this doesn't help.
Simple left join would do the trick.
Try this out and let me know in case of any queries.
select a.id,a.name,b.value
from
table a
left join
(select name,max(value) as value from table group by name) b
on a.name=b.name;
You may use this query. The table is joined with a subquery (table t2) that contains the results you want to update your table with:
UPDATE `table` t1,
(SELECT Name, MAX(Value) maxv, MIN(Value) minv
FROM `table`
GROUP BY Name
HAVING COUNT(*)>1 AND maxv != minv) t2
SET t1.Value = t2.maxv
WHERE t1.Name = t2.Name;
If you want to know how will the values be updated, you can first run an equivalent SELECT query:
SELECT t1.*, t2.maxv
FROM `table` t1,
(SELECT Name, MAX(Value) maxv, MIN(Value) minv
FROM `table`
GROUP BY Name
HAVING COUNT(*)>1 AND maxv != minv) t2
WHERE t1.Name = t2.Name;
This query will display all the fields of table, followed by the new value maxv. You can check the current value and the new value, and if it looks fine, you may run the UPDATE query.
I have a table like the following:
| ID | Short Name | Long Name |
|----|------------|-----------|
| 1 | s1 | l2 |
| 2 | s1 | l2 |
| 3 | s1 | l2 |
| 4 | s5 | l6 |
| .. | ... | |
I want to get all records that share the same Short Name and Long Name. I need their shared short name, long name, and 3 duplicates' IDs. For this particular example, I want {s1, l2, 1,2,3}
This is a fairly simple problem to solve. Basically what you want to do is write a subquery that counts the number of rows that match on your specified field for each row in your query. I have included a few examples below.
Find all rows that are duplicates and match on both name fields
SELECT * FROM TableName WHERE (SELECT COUNT(*) FROM TableName AS T2 WHERE T2.ShortName = TableName.ShortName AND T2.LongName = TableName.LongName) > 1;
Find all rows that are duplicates and match on the short name
SELECT * FROM TableName WHERE (SELECT COUNT(*) FROM TableName AS T2 WHERE T2.ShortName = TableName.ShortName) > 1;
Find all rows that are duplicates and match on the long name
SELECT * FROM TableName WHERE (SELECT COUNT(*) FROM TableName AS T2 WHERE T2.LongName = TableName.LongName) > 1;
Simply use a a self join of your table and select those rows where the two names are equal and the ids differ:
SELECT *
FROM <table> t1, <table> t2
WHERE t1.id <> t2.id
AND t1.short_name = t2.short_name
AND t1.long_name = t2.long_name;
You can use exits to see if there are any other data exists with the same condition where ID is not same.
select t1.* from table_name t1
where exists (
select 1 from table_name t2
where
t1.ID <> t2.ID
and t1.`Short Name` = t2.`Short Name`
and t1.`Long Name` = t2.`Long Name`
);
My question is how do i update a value in a table if it does not exists on another table.I checked INSERT ... ON DUPLICATE KEY UPDATE
but it describes about inserting something which updates and not insert.
My situation is like, i have two tables say (t1,t2). I want to update a column in t1 with a value if its not present in t2. Otherwise increment the value and try the update again.
So i want something like
update t1 set column = 'value' if it does not exists in t2
Can somebody suggest a solution
Here is a way to do it using the JOIN.
create table tab1 (id int , val int);
insert into tab1 values (1,1),(2,3),(3,5);
create table tab2 (id int , val int);
insert into tab2 values (4,1),(2,3),(3,5);
In the above tab1 (id = 1) not available in tab2 and using the following command we can update such values
update tab1 t1
left join tab2 t2 on t1.id = t2.id
set t1.val =
case
when t2.id IS NULL then 8
else t1.val
end
The output after the update command will look like
mysql> select * from tab1 ;
+------+------+
| id | val |
+------+------+
| 1 | 8 |
| 2 | 3 |
| 3 | 5 |
+------+------+
Also you can use EXIST which is also pretty better than doing left join
update tab1 t1 set t1.val = 10
where NOT EXISTS
(
select 1
from tab2 where tab2.id = t1.id
)
Table 1
id(int) | name(varchar)
1 | at,bat
2 | cat,at,bat,mat
3 | mat,cat
4 | sat,bat
Table 2
id(int) | type(varchar)
1 | at
2 | mat
As you can see table1 contains csv strings. Now I need to fetch the ids from Table 1 whose names exist in Table2 type field.
Is there any pure mysql query way of doing this? if not, what would be the most time efficient way of doing this in case of large record sets?
I would use FIND_IN_SET(str,strlist):
select distinct t1.id
from table1 t1
join table2 t2 on find_in_set(t2.type, t1.name) > 0
Working example: http://sqlfiddle.com/#!2/b642c/4
See here
select a.ids as id1, b.ids as id2, a.name,b.type
from table1 a
inner join table2 b on find_in_set(b.type,a.name)
Say I have the following 2 tables,
CREATE TABLE t1(
name VARCHAR(25) NOT NULL,
time INT,
a INT
);
CREATE TABLE t2(
name VARCHAR(25) NOT NULL,
time INT,
b INT
);
and Im looking to pull all the values (a) out of t1 with a given time, all the values with the previous time (say just time-1 for convenience) then for each name subtract the newer one from the older one and insert those values into t2 with the same time. The slow way of doing this would involve doing something like
SELECT name, a FROM t1 WHERE time = x;
SELECT name, a FROM t1 WHERE time = x-1;
(subtract the as for each name)
INSERT INTO t2 VALUES ....;
From my (limited) understanding of subqueries, there should hopefully be a way to do this all in 1 query. Any ideas? Thanks in advance :)
It looks like you can use the INSERT ... SELECT syntax:
INSERT INTO t2 (name, time, b)
SELECT ta.name, ta.time time, (ta.a - tb.a) b
FROM t1 ta
JOIN t1 tb ON (tb.time = ta.time - 1 AND tb.name = ta.name);
Test case:
INSERT INTO t1 VALUES ('t1', 1, 100);
INSERT INTO t1 VALUES ('t1', 2, 200);
INSERT INTO t1 VALUES ('t1', 3, 500);
INSERT INTO t1 VALUES ('t1', 4, 600);
INSERT INTO t1 VALUES ('t1', 5, 800);
INSERT INTO t1 VALUES ('t1', 6, 900);
Result:
SELECT * FROM t2;
+------+------+------+
| name | time | b |
+------+------+------+
| t1 | 2 | 100 |
| t1 | 3 | 300 |
| t1 | 4 | 100 |
| t1 | 5 | 200 |
| t1 | 6 | 100 |
+------+------+------+
5 rows in set (0.00 sec)
there is im mysql insert ... select
INSERT INTO table ( fields )
SELECT fields FROM table;