MySQL INSERT after JOIN - mysql

I have two tables as shown below.
table1
site | Link type
-----+----------
A | pdf
B | html
C | NULL
D | NULL
Table2
site | link type
-----+----------
C | htm
D | doc
This is the result I want:
site | link type
-----+----------
A | pdf
B | html
C | htm
D | doc
I want an insert query to insert the values of link type from table 2 to table 1
where link type is null joined with the condition with of table1.site = table2.site.
I tried:
INSERT INTO table1(linktype)
SELECT linktype FROM table1 t1
JOIN table2 t2
ON t1.site=t2.site
I want a insert query. as update query is working and want to know how a insert can be done?

Edit: Completely edited after clarification:
Creation of table1:
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS `table1`;
CREATE TABLE `table1` (
`site` varchar(250) DEFAULT NULL,
`linktype` varchar(250) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `table1` VALUES ('A', 'pdf');
INSERT INTO `table1` VALUES ('B', 'html');
INSERT INTO `table1` VALUES ('C', null);
INSERT INTO `table1` VALUES ('D', null);
Creation of table2:
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS `table2`;
CREATE TABLE `table2` (
`site` varchar(250) DEFAULT NULL,
`linktype` varchar(250) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `table2` VALUES ('C', 'htm');
INSERT INTO `table2` VALUES ('D', 'doc');
Insert query:
INSERT INTO
table1
(site, linktype)
(
SELECT
table2.site,
table2.linktype
FROM
table2
JOIN
table1
ON
table1.site = table2.site
)
;
Table1 after insert query:

Related

CONCAT with JOIN: create only one row per id although multiple rows for id

I'm using MySQL.
I have the following sample schema:
CREATE TABLE `my_table1` (
`id` int(5) NOT NULL,
`column1` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`column2` varchar(255) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `my_table1` (`id`, `column1`, `column2`) VALUES
(1, 'George', 'something'),
(2, 'Peter', 'anything');
CREATE TABLE `my_table2` (
`id` int(5) NOT NULL,
`column1` varchar(255) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `my_table2` (`id`, `column1`) VALUES
(1, 'DDD'),
(1, 'HHH'),
(1, 'FFF'),
(2, 'LLL'),
(2, 'TTT');
I want to merge all columns of my_table1 into one new column called new_column. Additionally I also want to merge the column1 from my_table2 to new_column where my_table1.id = my_table2.id.
If there are multiple rows with my_table1.id = my_table2.id in my_table2 I want to merge them all in new_column in the same row.
So, expected output for my tables is the following:
id
new_column
1
George something DDD HHH FFF
2
Peter anything LLL TTT
I tried the following query:
SELECT my_table1.id
, CONCAT_WS(' ', my_table1.column1, my_table1.column2, my_table2.column1) AS new_column
FROM my_table1
LEFT
JOIN my_table2
ON my_table1.id = my_table2.id;
I got the following result:
id
new_column
1
George something DDD
1
George something HHH
1
George something FFF
2
Peter anything LLL
2
Peter anything TTT
Here you can see a MySQL fiddle.
What can I do to receive the expected output?
This is a JOIN and GROUP_CONCAT():
SELECT
my_table1.id,
CONCAT_WS (' ', my_table1.column1, my_table1.column2, GROUP_CONCAT(my_table2.column1 SEPARATOR ' ')) AS new_column
FROM my_table1
LEFT JOIN my_table2
ON my_table1.id = my_table2.id
GROUP BY my_table1.id
Here's a fiddle of the working query.

How to retrieve data from table with join

I'm using MySQL 5.5. with two tables in it:
DROP TABLE IF EXISTS `events_dictionary`;
CREATE TABLE `events_dictionary` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `events_dictionary` VALUES (1, 'Light'),(2, 'Switch'),(3, 'on'),(4, 'off');
DROP TABLE IF EXISTS `events_log`;
CREATE TABLE `events_log` (
`log_id` bigint(20) NOT NULL AUTO_INCREMENT,
`event_name_id` int(11) NOT NULL DEFAULT '0',
`event_param1` int(11) DEFAULT NULL,
`event_value1` int(11) DEFAULT NULL,
PRIMARY KEY (`log_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `events_log` VALUES (1, 1, 2, 3),(2, 1, 2, 4);
Table events_dictionary contains names for events_log events names,params and values.
So, my question is - how could i select data from event_log table with columns event_name_id, event_param1, event_value1 mapped to name values from events_dictionary table?
I tried to do this query:
SELECT name, event_param1, event_value1
FROM events_log
JOIN events_dictionary ON events_log.event_name_id = events_dictionary.id;
But, in this case i see only event_name_id replaced with values from events_dictionary, like this:
name | event_param1 | event_value1
Light | 1 | 1
Light | 1 | 2
And i want to replace event_param1, and event_value1 with names from events_dictionary too.
Thanks in advance!
You need to join to the events_dictionary multiple times
SELECT a.name, b.name, c.name
FROM events_log
JOIN events_dictionary a ON events_log.event_name_id = a.id
JOIN events_dictionary b ON events_log.event_param1 = b.id
JOIN events_dictionary c ON events_log.event_value1 = c.id;
PS
Your example for the event_log isn't that helpful , instead insert the values (1,1,2,3),(2,1,2,4) to turn the switch on and off for the light.
DS
You can use correlated subqueries:
SELECT name,
(SELECT t.name
FROM events_dictionary AS t
WHERE t.id = event_param1) AS param_name,
(SELECT t2.name
FROM events_dictionary AS t2
WHERE t2.id = event_value1) AS event_name
FROM events_log AS el
JOIN events_dictionary AS ed ON el.event_name_id = ed.id;
Demo here

Add records randomly between select result

I want to add records randomly in select result like this example:
1 a
2 a
- b
3 a
- b
4 a
5 a
6 a
- b
7 a
8 a
- b
In a simple query I select from a table but in this case I want result mix with b table without random a result otherwise I simply could union them and then order random().
EDIT:
-- ----------------------------
-- Table structure for t1
-- ----------------------------
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
INSERT INTO `t1` VALUES ('1', 'a');
INSERT INTO `t1` VALUES ('2', 'a');
INSERT INTO `t1` VALUES ('3', 'a');
INSERT INTO `t1` VALUES ('4', 'a');
INSERT INTO `t1` VALUES ('5', 'a');
INSERT INTO `t1` VALUES ('6', 'a');
INSERT INTO `t1` VALUES ('7', 'a');
INSERT INTO `t1` VALUES ('8', 'a');
INSERT INTO `t1` VALUES ('9', 'a');
INSERT INTO `t1` VALUES ('10', 'a');
-- ----------------------------
-- Table structure for t2
-- ----------------------------
DROP TABLE IF EXISTS `t2`;
CREATE TABLE `t2` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `t2` VALUES ('1', 'b');
INSERT INTO `t2` VALUES ('2', 'b');
INSERT INTO `t2` VALUES ('3', 'b');
So I can union two tables and then order by random and the result will be like this:
SELECT
t1.ID,
t1.name
FROM
t1
UNION ALL
SELECT
t2.ID,
t2.name
FROM
t2
ORDER BY RAND();
5 a
2 a
6 a
3 a
7 a
2 b
9 a
1 a
10 a
3 b
4 a
8 a
1 b
But I don't want to random records I just only want mix two tables records like first example.
I hope my question is now clear.
I don't think pure SQL is the best solution here, I would do it in some end framework (I don't know what you use), like PHP, Delphi, Java, etc. This way is more easier and you can control it better. But if you would like to do it in SQL, here an idea:
SET #max_t1 = (SELECT MAX(ID) FROM t1);
SET #max_t2 = (SELECT MAX(ID) FROM t2);
SET #last_order = RAND()*#max_t1/#max_t2;
SELECT
t1.ID, t1.name, t1.ID AS "Ord"
FROM
t1
UNION ALL
SELECT
t2.ID, t2.name, #last_order:=#last_order+RAND()*#max_t1/#max_t2
FROM
t2
ORDER BY Ord
This way we generate a random position for TableB, then in every row we add some random value to it, in according to the size differency between the two tables, then order the whole result on this column.

Mysql UPDATING statement in datetime

i know its kind of weird but mind if somebody there look for this...
i have a 2 table which is
tableA
id | name | datetime -> format is int(11), varchar(128) datetime()
1 | 'foo bar' | '2014-08-04 00:53:16''
tableB
id | name | datetime | -> format is the same
1 | 'foo bar ' | null
using this statement
UPDATE tableA a
inner join tableB b on b.name = a.name
SET a.datetime = b.datetime
its say
Error Code: 1292. Truncated incorrect time value: '840:53:16';
what the... :)
if i select this using its own format
select * from tableA a inner join tableB b on b.name = a.name
its show
id | name | datetime |id | name | datetime |
1 | 'foo bar' | '2014-08-04 00:53:16'' | 1 | 'foo bar ' | null
am i doing something wrong??
if i use
show create table tableA
CREATE TEMPORARY TABLElist_of_in(
idint(11) NOT NULL,
namevarchar(128) NOT NULL,
datetimedatetime NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
show create table tableB
CREATE TEMPORARY TABLElist_of_in(
idint(11) NOT NULL,
namevarchar(128) NOT NULL,
datetimedatetime NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
by the way , im creating store procedure right now and its working in my localhost
but when i try it to the server, its not working and, after 6 hours i found out that this is the part that is not working...
by the way thanks for reading eheheh :))
I can't replicate your problem.
I recreated your tables, and when I run your query, it replaces tableA's datetime with the null from tableB. I'm guessing that you've built a simplified model of what is actually happening in your database? If that's the case, then the model you've made no longer highlights the problem.
What I did notice though, is that the error you are getting, is suggesting that the date format for one field doesn't match the other. I would check that both fields are in fact datetime, and that one isn't actually a varchar with the date in it.
Here's the dump of the sql to create my testing environment. If you run this (which will wipe TableA and TableB BTW), then run the query yourself, it should succeed.
# Dump of table tableA
# ------------------------------------------------------------
DROP TABLE IF EXISTS `tableA`;
CREATE TABLE `tableA` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) DEFAULT NULL,
`datetime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
LOCK TABLES `tableA` WRITE;
/*!40000 ALTER TABLE `tableA` DISABLE KEYS */;
INSERT INTO `tableA` (`id`, `name`, `datetime`)
VALUES
(1,'foobar','2014-08-04 00:53:16');
/*!40000 ALTER TABLE `tableA` ENABLE KEYS */;
UNLOCK TABLES;
# Dump of table tableB
# ------------------------------------------------------------
DROP TABLE IF EXISTS `tableB`;
CREATE TABLE `tableB` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) DEFAULT NULL,
`datetime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
LOCK TABLES `tableB` WRITE;
/*!40000 ALTER TABLE `tableB` DISABLE KEYS */;
INSERT INTO `tableB` (`id`, `name`, `datetime`)
VALUES
(1,'foobar',NULL);
/*!40000 ALTER TABLE `tableB` ENABLE KEYS */;
UNLOCK TABLES;

Best and optimal way to join max value from other table

I want to find the optimal way to run this query, here the details, lets say the following are my tables with their data:
-- User Table
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
-- Entries
INSERT INTO `users` VALUES (1,'user_a');
INSERT INTO `users` VALUES (2,'user_b');
INSERT INTO `users` VALUES (3,'user_c');
-- User Log Table
DROP TABLE IF EXISTS `user_log`;
CREATE TABLE `user_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`idrel` int(11) NOT NULL,
`event` varchar(20) NOT NULL,
`log` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `idrel` (`idrel`,`log`)
) ENGINE=MyISAM;
-- Entries
INSERT INTO `user_log` VALUES (1,1,'log1','2014-01-01 13:00:00');
INSERT INTO `user_log` VALUES (2,1,'log2','2014-01-02 13:00:00');
INSERT INTO `user_log` VALUES (3,2,'log3','2014-01-03 13:00:00');
INSERT INTO `user_log` VALUES (4,2,'log4','2014-01-04 13:00:00');
INSERT INTO `user_log` VALUES (5,3,'log5','2014-01-05 13:00:00');
INSERT INTO `user_log` VALUES (6,3,'log6','2014-01-06 13:00:00');
And I want to query the users joining the latest event logged, I have found two ways to do this but I don't know which one is the best (talking about speed when both tables grow) or if there is another way, here are my queries:
-- Query 1
SELECT
u.id,
u.name,
l2.event as last_record
FROM
users AS u
INNER JOIN
(
SELECT
idrel,
MAX(id) as last_id
FROM user_log
GROUP BY
idrel
) AS l1
ON (l1.idrel = u.id)
INNER JOIN
user_log AS l2
ON (l2.id = l1.last_id);
Which gives me this result:
+----+--------+-------------+
| id | name | last_record |
+----+--------+-------------+
| 1 | user_a | log2 |
| 2 | user_b | log4 |
| 3 | user_c | log6 |
+----+--------+-------------+
3 rows in set (0.00 sec)
-- Query 2
SELECT
u.id,
u.name,
(
SELECT event FROM user_log WHERE idrel = u.id ORDER BY log DESC LIMIT 1
) AS last_record
FROM
users AS u;
And the result:
+----+--------+-------------+
| id | name | last_record |
+----+--------+-------------+
| 1 | user_a | log2 |
| 2 | user_b | log4 |
| 3 | user_c | log6 |
+----+--------+-------------+
3 rows in set (0.00 sec)
Which one could be the best way? Is there any other better way?
Don’t do it that way, here is a better way, first, add a field to store on the users table the last ID of any new log entry, then create a trigger that updates that field on each new field inserted, then (optional) create a view to have a complete “table” to query from.
-- Add new field to save the modified id
ALTER TABLE `users` ADD `last_mod_id` INT(11) NOT NULL, ADD INDEX (`last_mod_id`);
-- Drop the trigger just in case it exists
DROP TRIGGER IF EXISTS `update_last_id`;
-- Create a trigger to save the last modified id each time a row is created
DELIMITER ;;
CREATE TRIGGER update_last_id
AFTER INSERT ON user_log
FOR EACH ROW
BEGIN
UPDATE `users`
SET `last_mod_id` = NEW.id
WHERE `id` = NEW.idrel;
END;
;;
-- Emtpy your table
TRUNCATE `user_log`;
-- Create all new registries
INSERT INTO `user_log` VALUES (1,1,'log1','2014-01-01 13:00:00');
INSERT INTO `user_log` VALUES (2,1,'log2','2014-01-02 13:00:00');
INSERT INTO `user_log` VALUES (3,2,'log3','2014-01-03 13:00:00');
INSERT INTO `user_log` VALUES (4,2,'log4','2014-01-04 13:00:00');
INSERT INTO `user_log` VALUES (5,3,'log5','2014-01-05 13:00:00');
INSERT INTO `user_log` VALUES (6,3,'log6','2014-01-06 13:00:00');
-- Query
SELECT
u.id,
u.name,
u.last_mod_id,
l.event,
l.log
FROM
`users` as u
INNER JOIN
`user_log` as l
ON (l.id = u.last_mod_id)
-- Drop view if exists
DROP VIEW IF EXISTS `users_log_view`;
-- View
CREATE VIEW `users_log_view` AS
SELECT
u.id,
u.name,
u.last_mod_id,
l.event,
l.log
FROM
`users` as u
INNER JOIN
`user_log` as l
ON (l.id = u.last_mod_id);
-- Query
SELECT * FROM `users_log_view` WHERE `id` = 1;