Mysql SELECT - How to select a column as an 'UNSELECTED' column? - mysql

I have 2 tables which contain many columns. example of my tables:
table1
_______________________________________________
| a | b | c | d | e | f | g | h | i | ... | z |
-----------------------------------------------
table2
_______________________________________________
| a | b | c | d | e | f | g | h | i | ... | z |
-----------------------------------------------
And now, I want to copy or insert a record from table1 to table 2. This is my query :
INSERT INTO table2
SELECT table1.* FROM table1
WHERE table1.b = '1'
I don't find any errors in query, but all I want is insert a record from all columns except column 'a' in table 1 to table2.
I can do it by this query :
INSERT INTO table2 (b,c,d,...) // it takes a long line
SELECT table1.b,table1.c,table1.d,... FROM table1 // it takes a long line
WHERE table1.b = '1'
But this is not an efficient query line, because i just don't select 1 column.
Is there any efficient way?

You could try duplicating the table with a create like statement, then alter it to drop the columns you don't want and do the insert into select with that new table. Then drop that new table. (or use a temp table)
CREATE TABLE table3 LIKE table1
ALTER TABLE table3 DROP COLUMN x
INSERT INTO table2
SELECT * FROM table3
DROP TABLE table3
and so forth.

Related

find all rows that have duplicate entries inside json column

I am stuck with a problem where I have a table with JSON column like this:
ID|VALUE
1 |{"a":"text1234","b":"default"}
2 |{"a":"text1234","b":"default"}
3 |{"a":"text1234","b":"text234"}
4 |{"a":"text1234","b":"default2"}
5 |{"a":"text1234","b":"default2"}
I would like to get all rows where value "b" is duplicate, so with the table above I would get rows 1,2,4,5.
I tried to group rows by value->b
$value_ids = ProductsAttributesValues::groupBy("value->b")->get();
but when i dd($value_ids) rows are not grouped by value->default. And I can't find a way to group them, so I can then count them. Or would there be a better way with doing this?
Try the json_extract function:
select count(id) dup_count, json_extract(`value`,"$.b") as dup_value
from test
group by json_extract(`value`,"$.b")
having dup_count>1
;
-- result set:
| dup_count | dup_value |
+-----------+------------+
| 2 | "default" |
| 2 | "default2" |
-- to get the id involved:
select id,dup_count,dup_value
from (select id,json_extract(`value`,"$.b") as dup_v
from test) t1
join
(select count(id) dup_count, json_extract(`value`,"$.b") as dup_value
from test
group by json_extract(`value`,"$.b")
having dup_count>1) t2
on t1.dup_v=t2.dup_value
;
-- result set:
| id | dup_count | dup_value |
+------+-----------+------------+
| 1 | 2 | "default" |
| 2 | 2 | "default" |
| 4 | 2 | "default2" |
| 5 | 2 | "default2" |
Here is the queries that can do your task.
/*Extract value of "b" - Step 1*/
DROP TEMPORARY TABLE IF EXISTS d1;
CREATE TEMPORARY TABLE d1
SELECT
ID, `VALUE`, SUBSTR(VALUE FROM POSITION(',"b":' IN VALUE)+5 FOR 1000) AS v
FROM mytest
;
/*Extract value of "b" - Step 2*/
DROP TEMPORARY TABLE IF EXISTS d2;
CREATE TEMPORARY TABLE d2
SELECT
ID, LEFT(v, LENGTH(v)-1) AS b
FROM
d1
;
ALTER TABLE d2 ADD INDEX b(b);
/* Search for duplicates */
DROP TEMPORARY TABLE IF EXISTS duplicates;
CREATE TEMPORARY TABLE duplicates
SELECT
b, COUNT(b) AS b_count
FROM
d2
GROUP BY b HAVING COUNT(b)>1
;
ALTER TABLE duplicates ADD INDEX b(b);
/* Display for duplicates */
SELECT
d2.ID, d2.b
FROM
d2
INNER JOIN duplicates ON d2.b=duplicates.b
;
This should give you :
1 "default"
2 "default"
4 "default2"
5 "default2"

mysql - How to update only the first row found from multiple duplicates rows

this is what I have, 2 tables, and i want to update table #2 with the stock from the first table, but i want to update only the first row of each duplicate.
+----+------+
|code|stock |
+----+------+
|5001| 40 |
|5002| 20 |
|5003| 60 |
+----+------+
+----+------+----+
|code|stock |lot |
+----+------+----+
|5001| | A | < Update this
|5001| | B |
|5002| | C | < Update this
|5003| | D | < Update this
|5003| | E |
+----+------+----+
So here i have the same product on two or more rows, and i want to update only the one from lot:A, lot:c, and lot: D, with the values from the first table.
How can i do this?
You could try using aupdate with join
update table2 t2
inner join (
select code, min(lot) lot
from table2
) t on t2.code = t.code and t2.lot = t.lot
inner join table1 t1 on t2.code = t1.code
set s2.stock = t1.stock

How to create table as select from multiple tables?

How do I go about creating a table from multiple tables having variable columns (union cannot be used)?
mysql> select * from a;
+------+------+
| id | name |
+------+------+
| 1 | Ruby |
+------+------+
mysql> select * from b;
+------+------+
| pid | name |
+------+------+
| 1 | Java |
| 1 | C++ |
+------+------+
What I want...
+------+------+------+------+
| id | name | pid | bname|
+------+------+------+------+
| 1 | Ruby | | |
| | | 1 | C++ |
| | | 1 | Java |
+------+------+------+------+
What I have tried.
mysql> create table t as select * from a; # worked fine
mysql> alter table t as select pid, name as bname from b; #didn't work
You can do this in this rather arcane way:
select a.*, b.*
from a left join
b
on 1 = 0
union all
select a.*, b.*
from b left join
a
on 1 = 0;
This is one way, in MySQL of implementing:
select a.*, b.*
from a full outer join
b
on 1 = 0;
But, it requires a union. You could do it in two steps if you want to avoid the union:
create table ab as
select a.*, b.*
from a left join
b
on 1 = 0;
insert into ab
select a.*, b.*
from b left join
a
on 1 = 0;
There's no problem to use union, you just need to select nulls as the columns that aren't in the table:
CREATE TABLE t AS
SELECT id, name, null AS pid, null AS bname
FROM a
UNION ALL
SELECT null, null, pid, bname
FROM b
Create the new table, containing all four columns. Then
INSERT INTO t (id, name) SELECT * FROM a;
INSERT INTO t (pid, bname) SELECT * FROM b;
The first line will put everything from a in there, and leave the other two fields as NULL; the second will do the corresponding thing from b. You could do the whole thing in one CREATE/UNION statement, but if this is a one-off operation, it's probably easier to understand what you're doing if you do it in stages like this.
You can try this this as an example.
Create a new table (name, date of birth) by joining two tables (student id, name) and (student id, date of birth).
Create first table:
create table stu1(student_id char(5) primary key,name varchar(45))ENGINE=innodb;
Create second table:
create table stu2(student_id char(5) primary key,dob date)ENGINE=innodb;
Create third table (by joining two tables):
create table stu3 AS(select stu1.name,stu2.dob from stu1,stu2
where stu1.student_id=stu2.student_id);

Efficient way to get DISTINCT rows of Table A when JOINing with Table B

Simple problem. Given example tables:
Table A:
id | type
---+-----
1 | A
2 | B
3 | C
Table B:
id | a_id | type
---+------+-----
1 | 1 | X
2 | 2 | Y
3 | 1 | X
4 | 3 | Z
(there are additional columns, which I omitted, in order to clarify the problem)
The query:
SELECT a.*
FROM a a
INNER JOIN b b ON b.a_id = a.id
WHERE b.type = 'X'
Result:
id | type
---+-----
1 | A
1 | A
SQL Fiddle: http://sqlfiddle.com/#!2/e6138f/1
But I only want to have distinct rows of Table A. I know, I could do SELECT DISTINCT a.*, but our Table A has about 40 columns, and this SELECT can return 100-10000 rows. Isn't that extremely slow, if the database has to compare each column?
Or is MySQL intelligent enough, to just focus on the Primary Key for the DISTINCT operation?
Thanks in advance :)
Use exists instead of an explicit join:
select a.*
from tablea a
where exists (select 1 from tableb b where b.a_id = a.id and b.type = 'x');
For performance, create an index on tableb(a_id, type).

MySQL insert from select query

I have two tables:
TABLE1
| ColumnA | ColumnB |
-----------------------
| 123 | 1 |
TABLE2
| ColumnA | ColumnC |
-----------------------
| 123 | 20 |
I altered Table 2 to add a new column, so it looks like this
NEW TABLE2
| ColumnA | ColumnC | ColumnB |
----------------------------------
| 123 | 20 | NULL |
Now, I want to select the values of TABLE1.Column B and insert it into TABLE2.Column B
So I wrote this query:
INSERT INTO TABLE2 (ColumnB)
SELECT t1.ColumnB
FROM TABLE1 AS t1
INNER JOIN
TABLE2 AS t2
ON t1.ColumnA = t2.ColumnA;
But it doesn't seem to do the trick. Am I missing something?
You need to use an UPDATE statement to update the table. An INSERT will add new rows.
UPDATE Table2
JOIN Table1
ON
Table2.columnA = Table1.ColumnA
SET
Table2.ColumnB = Table1.ColumnB
WHERE
Table2.ColumnB IS NULL
You don't appear to want to insert. It appears you want to update the rows already in table2. You can use:
update table2 set ColumbB=(select ColumnB from table1 where table1.ColumnA=table2.ColumnA)