Couldn't find a solution yet... although it is probably a newbie question, I haven't been able to overcome... hope someone can give a hand.
I have a MySQL table that has:
Blockquote
Col1 Col2
Row1 A null
Row2 A A1
Row3 A null
Row4 B null
Row5 B B1
etc
> Blockquote
How do I construct an SQL update to update Col2, so that the values on Col2 replace the null, ie, C2R1 and C2R3 gets A1, and C2R4 gets B1 ?
You can calculate the required values as follows:
CREATE TEMPORARY TABLE yourtemptable AS
SELECT yourtable.col1, T1.col2
FROM yourtable
JOIN
(
SELECT col1, MAX(col2) AS col2
FROM yourtable
GROUP BY col1
) T1
ON yourtable.col1 = T1.col1
You can then either drop/truncate the original table and recreate it using these values, or if you can't drop the table you can instead perform a multi-table update.
Although it might not work (because the MySQL documentation states that Currently, you cannot update a table and select from the same table in a subquery.), you should try with something like:
UPDATE table1 SET col2 = (SELECT t2.col1 FROM table1 t2 WHERE t2.col1 = table1.col1 AND NOT t2.col2 IS NULL LIMIT 1) WHERE table1.col2 IS NULL
Related
I found a strange bug (I guess) in mariadb
Suppose you have a table table1 with col1 and other table2 with col1 and you want to list all row in table1 whose col1 values exist in table2.
We could code this as:
select *
from table1
where col1 in (
select col1 from table2
)
The result contains the expected rows if all data in col1 in table2 are not null.
However, if any values from table2 are null then it returns no rows.
This is unexpected to me and scary as I've used this clause many times.
This is how in is defined to work in SQL: if any of the values in the list used by in are null, none match.
See "Law of the excluded fourth" section of https://en.wikipedia.org/wiki/Null_(SQL) for more info.
All SQL databases behave this way.
I normally use exists, so I haven't struck this problem
select * from table1 t1
where exists (select t2.col1 from table2 t2
where t2.col1 = t1.col1)
Not Tested
I am trying to update a column here. When I run select statement, it gives proper results. But I am not able to update. Here is the script that I am running....
update table1
set col1 = 0
where col1 = 1 and col2 not in (select col3 from table1);
MySQL does not allow subqueries to reference the table being updated. So, use a left join instead:
update table1 t1 left join
table1 tt1
on t1.col2 = tt1.col3
set col1 = 0
where t1.col1 = 1 and tt1.col3 is null;
I also strongly advise you not to use not in with subqueries. The not in doesn't usually do what you intend when any value in the subquery is NULL. Hence, it is just a bad practice to use something that sometimes does not do what you intend.
I have an UPDATE and SELECT statement working in SQL however I am unable to replicate the same outcome in MYSQL.
I have a table (TBL1) with, say 4 columns:-
col1: registration (VARCHAR)
col2: date
col3: oldest date flag (values Y or blank)
col4: index (priamry key - auto-increment).
An ongoing process continues to add registrations and dates to the table. After a batch of additions any col3 'Y' flags will be removed and then an update process will set the col3 value = 'Y' for each the row where the registration has the oldest date.
Here is the SQL code, this works as expected after an earlier process removes any previous col3 'Y' values;-
UPDATE T1
SET T1.Col3 = 'Y'
SELECT FROM TBL1 AS T1
INNER JOIN ( SELECT Col1 AS REG, MIN(Col2) AS MINDATE
FROM TBL1
GROUP BY Col1) AS T2
ON T1.Col1 = T2.REG and T1.Col2 = T2.MINDATE
The result correctly recognises for each unique registration the oldest date and sets 'Y' in col3.
I need to replicate this process in MYSQL but after much effort I can't find a way to do this?
If you are just looking for the same logic, but with MySQL's update join syntax, then try this:
UPDATE TBL1 T1
INNER JOIN
(
SELECT Col1 AS REG, MIN(Col2) AS MINDATE
FROM TBL1
GROUP BY Col1
) AS T2
ON T1.Col1 = T2.REG and T1.Col2 = T2.MINDATE
SET T1.Col3 = 'Y';
Why would I use a LEFT JOIN in SQL in a FROM clause and attach a WHERE clause where the entity "is null"? I was told this is a very efficient script and I should learn the methodology behind it.
For example:
FROM
something
LEFT JOIN aRow a AND bRow b AND cRow c AND dRow d
WHERE
bRow.b IS NULL;
This kind of construct is used when you specifically want to know something like "a list of all customers who have never ordered anything" :
SELECT
customer.*
FROM
customers
LEFT JOIN
orders
ON
orders.customerid = customers.id
WHERE
orders.id IS NULL
Or to quote an old manager of mine: "Can you get the database to give me a list of everything that isn't in the database?"
Me> "Sure, can you give me a list of what things the database should tell you it doesn't have?"
Him> "How am I supposed to know that?"
This really is a fairly generic, non-RDBMS-specific question. The logic will apply to pretty much any flavor of SQL. And this is a technique that anyone who works with data queries should be familiar with.
For all intents and purposes (and moving past the flawed syntax in the OP), this is the same query as:
SELECT *
FROM table1
WHERE table1.col1 NOT IN (
SELECT table2.col1 FROM table2 WHERE table2.col2 = <filterHere>
)
When you are dealing with a couple of hundred rows, you may not see a significant difference in performance. But when you're working with just a few million rows in both tables, you will most definitely see a significant performance increase in
SELECT table1.*
FROM table1
LEFT OUTER JOIN table2 ON table1.col1 = table2.col1
AND table2.col2 = 42
WHERE table2.id IS NULL
Let's illustrate what is happening with these queries.
Create test tables.
CREATE TABLE table1 (col1 int, col2 varchar(10)) ;
INSERT INTO table1 ( col1, col2 )
VALUES (1,'a')
, (2,'b')
, (3,'c')
, (4,'d')
CREATE TABLE table2 (col1 int, col2 varchar(10)) ;
INSERT INTO table2 ( col1, col2 )
VALUES (1,'a')
, (3,'c')
This gives us
table1
col1 col2
1 a
2 b
3 c
4 d
table2
col1 col2
1 a
3 c
Now we want the columns that are in table1 but not in table2.
SELECT t1.col1, t1.col2
FROM table1 t1
WHERE t1.col1 NOT IN (
SELECT t2.col1 FROM table2 t2
)
We can't SELECT anything from table2, because that table is just a sub-query and not part of the whole query. It's not available to us.
This breaks down to
SELECT t1.col1, t1.col2
FROM table1 t1
WHERE t1.col1 NOT IN ( 1,3 )
Which further breaks down to
SELECT t1.col1, t1.col2
FROM table1 t1
WHERE t1.col1 <> 1
OR t1.col1 <> 3
These queries give us
col1 col2
2 b
4 d
That's a subquery broken down into 2 different OR statements to filter our results.
So lets look at a JOIN. We want all of the records on the left side, and only include those on the right side that match. So
SELECT t1.col1 AS t1_col1, t1.col2 AS t1_col2, t2.col1 AS t2_col1, t2.col2 AS t2_col2
FROM table1 t1
LEFT OUTER JOIN table2 t2 ON t1.col1 = t2.col1
With a JOIN, both tables are available to our SELECT, so we can see which records in tablel2 match up to those in table1. The above gives us
t1_col1 t1_col2 t2_col1 t2_col2
1 a 1 a
2 b NULL NULL
3 c 3 c
4 d NULL NULL
With the extra data, we can see that col1 for 2 and 4 don't match in the two tables. We can now filter those out with a simple WHERE statement.
SELECT t1.col1, t1.col2
FROM table1 t1
LEFT OUTER JOIN table2 t2 ON t1.col1 = t2.col1
WHERE t2.col1 IS NULL
Giving us
col1 col2
2 b
4 d
There's no subquery and just one statement in the filter. Plus, this allows the engine's optimizer to make a more efficient query plan.
It's impossible to see a difference in performance when we're only dealing with a couple of rows, but multiply these tables by a few million rows, and you will definitely see how much faster a JOIN can be.
i am performing a sub query in mysql which is like
select col1, col2 , (select col3 from table2) as 'data'
from table1
where not data is null
how should i get data in where clause. IS it POSSIBLE
One way to do this is :
SELECT *
FROM (
select col1, col2 , (select col3 from table2) as 'data'
from table1
)t
WHERE data IS NOT NULL
As you see there I have created on derived table t for your query, now result of your query is treated as Table(temp table) and having columns as col1,col2 and col3, Using this result set we can able to access col3 in where clause .
Note - assuming that select col3 from table2 returns single value as per OP's comments
Use cross join:
select t1.col1, t1.col2, t2.col3 as data
from table1 t1 cross join
(select col3 from table2) t2
where t2.col3 is not null;