Using Join and Insert Statement in MySQL - mysql

I have an insert statement like this
INSERT INTO T_WorkContents ( user_id, working_date, working_start_time,
working_end_time, break_time, holiday_mark,
overtime_hours, overtime_reason, work_detail,
remarks, regist_user, regist_date,
update_user, update_date )
VALUES ( '00005', '2015-02-05', '8:0',
'17:0', '0:0', '0',
'0:0', NULL, NULL,
NULL, '00005', current_timestamp(),
'00005', current_timestamp()
);
I want to check whether the user is already deleted when insert the new row by join the table workcontent with the table user info on user_id and the condition is where userinfo.delete_flag = 0.
is there any way to do it?

I'm not sure I understand your question. But if you would like to only perform the insertion if the corresponding user exists and is marked as not deleted in your other table this should work:
INSERT INTO T_WorkContents ( user_id, working_date, working_start_time,
working_end_time, break_time, holiday_mark,
overtime_hours, overtime_reason, work_detail,
remarks, regist_user, regist_date,
update_user, update_date )
SELECT '00005', '2015-02-05', '8:0',
'17:0', '0:0', '0',
'0:0', NULL, NULL,
NULL, '00005', current_timestamp(),
'00005', current_timestamp()
FROM userinfo ui
WHERE ui.user_id = '00005' && ui.delete_flag = 0
If the userinfo doesn't contain a row with a user_id equal to 00005 and a delete_flag that is set to 0 then the select will return no rows and the insert query will in turn affect no rows.

You can use WHERE EXISTS. Try below
INSERT INTO funds (field1, field2)
values (x, xx)
WHERE EXISTS (
SELECT *
FROM table
WHERE userid = your_user_id
);

Related

how insert registers of today from another table mysql

I'm trying to count the records in my "records" table and insert in results table but I just want to count today's records.
Below you will see some alternatives that I tried (I'm using MySQL), but I keep getting this error:
You have a syntax error in your SQL next to '' on line 2
INSERT INTO results (Data,total)
VALUES (now(), (SELECT COUNT(*) FROM records WHERE Data = now());
This SQL also causes an error:
INSERT INTO results (Data, total)
VALUES (now(), (SELECT COUNT(record.ID) AS day FROM record
WHERE date(Data) = date(date_sub(now(), interval 0 day));
and then
INSERT INTO resultS (Data,total)
VALUES (now(), (SELECT COUNT(*) FROM records
WHERE Data >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY));
And yet another attempt:
INSERT INTO results (Data, Total)
VALUES (now(), (SELECT COUNT(*) FROM records
WHERE DATE(Data)= CURRENT_DATE() - INTERVAL 1 DAY));
This is my sql config man:
CREATE TABLE `records`
(
`ID` char(23) NOT NULL,
`Name` varchar(255) NOT NULL,
`Total` int(255) NOT NULL,
`Data` date NOT NULL,
`QrCode` varchar(255) NOT NULL,
`City` varchar(255) NOT NULL,
`Device` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `results`
(
`id` int(11) NOT NULL,
`total` int(11) NOT NULL,
`Data` date DEFAULT NULL,
`grown` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
You have defined grown column as not null so you cannot put there NULL.
My query works :
INSERT INTO results
VALUES (1, (SELECT COUNT(1) FROM records WHERE Data= now()), now(), 1);
You should define default value for grown column. Same situation you have with column id. You should define sequence for column id:
id NOT NULL AUTO_INCREMENT;
INSERT INTO results (Data, total)
SELECT CURRENT_DATE(), COUNT(*)
FROM records
WHERE DATE(Data) = CURRENT_DATE();

Column count doesn't match value count at row 1 in MySQL

I have created a table with the following query:
CREATE TABLE `dailydata` (
`id` int(9) NOT NULL,
`Date` varchar(100) NOT NULL,
`EmpID` varchar(100) NOT NULL,
`name` varchar(100) NOT NULL,
`TeamName` varchar(100) NOT NULL,
`active` varchar(100) NOT NULL,
`idle` double NOT NULL,
`Stime` double NOT NULL,
`Etime` varchar(100) NOT NULL,
`Inofficehr` decimal(20,2) NOT NULL,
`activehr` double(19,2) NOT NULL,
`idlehr` double(19,2) NOT NULL,
`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Set Primary key For 'id' column:
ALTER TABLE `dailydata`ADD PRIMARY KEY (`id`);
Now I'm trying to insert the data with this code:
INSERT INTO dailydata
SELECT A.Date, A.EmpID, B.name, B.TeamName,
SUM(CASE WHEN State = 'active' THEN A.MinutesatState ELSE 0 END) AS active,
SUM(CASE WHEN State = 'idle' THEN A.MinutesatState ELSE 0 END) AS idle,
Min(A.Statestarttime) AS Stime, MAX(A.StateEndtime) AS Etime,
ROUND((TIME_TO_SEC(MAX(A.StateEndtime))/60 -
TIME_TO_SEC(MIN(A.StateStarttime))/60)/60,2) as Inofficehr,
ROUND(SUM(CASE WHEN State = 'active' THEN A.MinutesatState ELSE 0 END)/60,2)
AS activehr,
ROUND(SUM(CASE WHEN State = 'idle' THEN A.MinutesatState ELSE 0 END)/60,2)
AS idlehr
FROM time A join ttld.login B on A.EmpID=B.username
WHERE A.Date='01-01-2019' AND A.Statestarttime <>'' AND A.StateEndtime <>''
GROUP BY A.EmpID;
But I'm getting this error:
#1136 - Column count doesn't match value count at row 1
I understand I have not define the ID in my insert code and the reason for it is I want it to auto populate.
How can I modify my INSERT query code to do so...
You have 13 columns in your table, but only 11 in your select, which is why you are getting this error.
But first, to make your id column auto-populate, you need to declare it as AUTO_INCREMENT. You can change it with an ALTER TABLE command:
ALTER TABLE dailydata CHANGE id id INT AUTO_INCREMENT PRIMARY KEY
Since you have a default value for your Timestamp column you don't need to insert a value for that.
To resolve the error you are seeing, you need to modify your INSERT query to to match the number of columns being inserted to the data either by
(a) naming the columns you are inserting; or
(b) inserting NULL values for the columns with no values (id and Timestamp)
e.g. (a)
INSERT INTO dailydata (`Date`, `EmpID`, `name`, `TeamName`, `active`, `idle` ,`Stime`, `Etime`, `Inofficehr`, `activehr`, `idlehr`)
SELECT A.Date, A.EmpID, B.name, B.TeamName,
...
e.g. (b)
INSERT INTO dailydata
SELECT NULL AS id,
A.Date, A.EmpID, B.name, B.TeamName,
...
NULL AS Timestamp
FROM ...

MySQL Query to Search using LIMIT and OFFSET on each Query of a UNION

This is more of a concept question I guess.
* discussion
discussionId
message
timestamp
* comment
commentId
message
timestamp
* tweet
tweetId
message
timestamp
Then on a page I list the first let's say 10 entries and with next will load the next 10. All normal there.
My question is: Is there a way to limit each query of the UNION or I can only do the LIMIT/OFFSET on the result of the UNION? I'm pondering because I was imagining if each table has like 1K (I know the number is very low), the query would return 3K results and then grab only 10. When the number of rows gets bigger, it wouldn't slow down the performance? Or even if in the future there are more tables that I want to do the UNION, it wouldn't be better to get x of each one of then and in the end get the desired 10? But I can't figure it out how I'll know which one was the last one of the limit/offset of the queries... so I'm afraid I would have to select all and use the limit on the UNION.
So instead of using
(SELECT
message,
timestamp
FROM
discussion
)
UNION
(SELECT
message,
timestamp
FROM
comment
)
UNION
(SELECT
message,
timestamp
FROM
tweet
)
LIMIT $offset, $limit
Is it possible to have
(SELECT
message,
timestamp
FROM
discussion
LIMIT $offset, $limit
)
UNION
(SELECT
message,
timestamp
FROM
comment
LIMIT $offset, $limit
)
UNION
(SELECT
message,
timestamp
FROM
tweet
LIMIT $offset, $limit
)
LIMIT $offset, $limit
Thanks for your help!
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE Message
(`id` int, `type_id` int, `message` varchar(10), `timestamp` int)
;
INSERT INTO Message
(`id`, `type_id`, `message`, `timestamp`)
VALUES
(1, 1, 'message1', 12345678),
(2, 2, 'message2', 12345679),
(3, 3, 'message3', 12345680)
;
CREATE TABLE Type
(`id` int, `type` varchar(10))
;
INSERT INTO Type
(`id`, `type`)
VALUES
(1, 'discussion'),
(2, 'comment'),
(3, 'tweet')
;
CREATE TABLE DiscussionDetail
(`id` int, `message_id` int, `from_user` varchar(10), `to_user` varchar(10))
;
INSERT INTO DiscussionDetail
(`id`, `message_id`, `from_user`, `to_user`)
VALUES
(1, 1, 'Peter', 'Anna')
;
CREATE TABLE CommentDetail
(`id` int, `message_id` int, `post_id` varchar(5), `user_id` varchar(5))
;
INSERT INTO CommentDetail
(`id`, `message_id`, `post_id`, `user_id`)
VALUES
(1, 2, 'post4', 'user6')
;
CREATE TABLE TweetDetail
(`id` int, `message_id` int, `twitteracct` varchar(6))
;
INSERT INTO TweetDetail
(`id`, `message_id`, `twitteracct`)
VALUES
(1, 3, 'myacct')
;
Query 1:
SELECT Message.*, type,
case when dd.id is not null then from_user
when cd.id is not null then post_id
when td.id is not null then twitteracct else '' end as detail1,
case when dd.id is not null then to_user
when cd.id is not null then user_id else '' end as detail2
FROM Message
INNER JOIN Type ON Type_Id = Type.id
LEFT OUTER JOIN DiscussionDetail dd ON dd.message_id = Message.id AND Type_Id = 1
LEFT OUTER JOIN CommentDetail cd ON cd.message_id = Message.id AND Type_Id = 2
LEFT OUTER JOIN TweetDetail td ON td.message_id = Message.id AND Type_Id = 3
ORDER BY timestamp LIMIT 1,1
Results:
| id | type_id | message | timestamp | type | detail1 | detail2 |
|----|---------|----------|-----------|---------|---------|---------|
| 2 | 2 | message2 | 12345679 | comment | post4 | user6 |
You can also create a VIEW for this :
CREATE VIEW AllMessages AS
SELECT Message.*, type,
case when dd.id is not null then from_user
when cd.id is not null then post_id
when td.id is not null then twitteracct else '' end as detail1,
case when dd.id is not null then to_user
when cd.id is not null then user_id else '' end as detail2
FROM Message
INNER JOIN Type ON Type_Id = Type.id
LEFT OUTER JOIN DiscussionDetail dd ON dd.message_id = Message.id AND Type_Id = 1
LEFT OUTER JOIN CommentDetail cd ON cd.message_id = Message.id AND Type_Id = 2
LEFT OUTER JOIN TweetDetail td ON td.message_id = Message.id AND Type_Id = 3
And then :
SELECT *
FROM AllMessages
ORDER BY timestamp LIMIT 1,1
SQL Fiddle
I like your question and I myself asked that once. I used the second solution of retrieving all and then paginate what I needed. Now, the problem is the performance, so here I will try to improve the performance of retrieving the rows, with several thousands of rows (this solution have to be tested, but I think it will work smoothly).
The tricky performance idea: Create a new table, only with ids of the tables, look for the timestamp (or the column that every table share and you use for ordering) and then filter by that. This way, you will have this:
SELECT insert_time
FROM all_tables_order
ORDER BY insert_time DESC
LIMIT 0,5
From there, you take the boundaries (First and last row result, to take the insert_time, you may see that in http://sqlfiddle.com/#!9/043c1/29), and then you create the big SQL, with that limits:
SELECT *
FROM (
SELECT t.id as id,
t.tweet as message,
t.insert_time as insert_time
FROM tweets t
WHERE insert_time <= '2015-08-06 21:53:30'
AND insert_time >= '2015-08-06 21:51:34'
UNION ALL
SELECT c.id as id,
c.`comment` as message,
c.insert_time as insert_time
FROM comments c
WHERE insert_time <= '2015-08-06 21:53:30'
AND insert_time >= '2015-08-06 21:51:34'
UNION ALL
SELECT m.id as id,
m.message as message,
m.insert_time as insert_time
FROM messages m
WHERE insert_time <= '2015-08-06 21:53:30'
AND insert_time >= '2015-08-06 21:51:34'
) AS myWholeTable
ORDER BY insert_time
This should be quite fast, despite the fact you're doing two queries, because your results are indexed, and you're only ordering small results: http://sqlfiddle.com/#!9/043c1/30
Your database schema should have something like the following, with the triggers there to update the indexes table:
Tables and datas:
CREATE TABLE IF NOT EXISTS `all_tables_order` (
`id` int(11) DEFAULT NULL,
`insert_time` timestamp NULL DEFAULT NULL,
`table_name` enum('comments','tweets','messages') DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `all_tables_order` (`id`, `insert_time`, `table_name`) VALUES
(1, '2015-08-06 21:50:52', 'messages'),
(2, '2015-08-06 21:51:34', 'comments'),
(1, '2015-08-06 21:52:10', 'tweets'),
(2, '2015-08-06 21:52:46', 'messages'),
(2, '2015-08-06 21:53:07', 'tweets'),
(3, '2015-08-06 21:53:30', 'comments'),
(1, '2015-08-03 21:53:39', 'comments');
CREATE TABLE IF NOT EXISTS `comments` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`comment` tinytext CHARACTER SET latin1,
`insert_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `Índice 1` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=COMPACT;
INSERT INTO `comments` (`id`, `comment`, `insert_time`) VALUES
(2, 'c1', '2015-08-06 21:51:34'),
(3, 'c3', '2015-08-06 21:53:30'),
(1, 'c2', '2015-08-03 21:53:39');
CREATE TABLE IF NOT EXISTS `messages` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`message` tinytext,
`insert_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `Índice 1` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `messages` (`id`, `message`, `insert_time`) VALUES
(1, 'm1', '2015-08-06 21:50:52'),
(2, 'm2', '2015-08-06 21:52:46');
CREATE TABLE IF NOT EXISTS `tweets` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`tweet` tinytext,
`created_by` int(11) DEFAULT NULL,
`insert_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
KEY `Índice 1` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=COMPACT;
INSERT INTO `tweets` (`id`, `tweet`, `created_by`, `insert_time`) VALUES
(1, 't1', 23, '2015-08-06 21:52:10'),
(2, 't2', 25, '2015-08-06 21:53:07');
Triggers:
DELIMITER //
CREATE TRIGGER `comments_before_insert` AFTER INSERT ON `comments` FOR EACH ROW BEGIN
insert into all_tables_order set insert_time = new.insert_time, id = new.id, table_name = 'comments';
END//
DELIMITER ;
CREATE TRIGGER `messages_after_insert` AFTER INSERT ON `messages` FOR EACH ROW BEGIN
insert into all_tables_order set insert_time = new.insert_time, id = new.id, table_name = 'messages';
END//
DELIMITER ;
DELIMITER //
CREATE TRIGGER `tweets_after_insert` AFTER INSERT ON `tweets` FOR EACH ROW BEGIN
insert into all_tables_order set insert_time = new.insert_time, id = new.id, table_name = 'tweets';
END//
DELIMITER ;

how to do group by and order by in one query?

I have two table one is 'tb_student' and other is 'tb_fees'
create query for 'tb_student'
CREATE TABLE `tb_student` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`class` varchar(255) NOT NULL,
`created_on` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
)
create query for 'tb_fees'
CREATE TABLE `tb_fees` (
`id` int(11) NOT NULL auto_increment,
`email` varchar(255) NOT NULL,
`amount` varchar(255) NOT NULL,
`created_on` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
)
In first table i am storing the student details and in other table storing the fees details
I want to select student details from 'tb_student' and last add fee from 'tb_fees' only for those student which are in class 6
so i tried this
SELECT *
FROM tb_student s INNER JOIN
tb_fees f on
s.email =f.email
WHERE s.class = 6 GROUP BY s.email ORDER BY f.created_on DESC
This will give result only the first created how to get last created values
fees table
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (5,'ram#gmail.com','5000','2013-05-01 14:20:15');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (6,'Sam#gmail.com','5000','2013-05-02 14:20:23');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (7,'jak#gmail.com','5000','2013-05-03 14:20:30');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (8,'Sam#gmail.com','5000','2013-05-29 14:20:35');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (9,'ram#gmail.com','5000','2013-05-30 14:20:39');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (10,'jak#gmail.com','5000','2013-05-30 14:36:13');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (11,'rose#gmail.com','5000','2013-05-30 14:36:15');
insert into `tb_fees`(`id`,`email`,`amount`,`created_on`) values (12,'nim#gmail.com','5000','2013-05-30 14:36:15');
Student table values
insert into `tb_student`(`id`,`name`,`email`,`class`,`created_on`) values (5,'Ram','ram#gmail.com','6','2013-04-30 14:00:56');
insert into `tb_student`(`id`,`name`,`email`,`class`,`created_on`) values (6,'Sam','Sam#gmail.com','6','2013-03-30 14:01:30');
insert into `tb_student`(`id`,`name`,`email`,`class`,`created_on`) values (7,'Nimmy','nim#gmail.com','7','2013-04-30 13:59:59');
insert into `tb_student`(`id`,`name`,`email`,`class`,`created_on`) values (8,'jak','jak#gmail.com','6','2013-03-30 14:07:32');
insert into `tb_student`(`id`,`name`,`email`,`class`,`created_on`) values (9,'rose','rose#gmail.com','5','2013-04-30 14:07:51');
Thank you
To get the latest fees something like this:-
SELECT s.* , f.*
FROM tb_student s
INNER JOIN
(SELECT email, MAX(created_on) AS created_on
FROM tb_fees
GROUP BY email) Sub1
ON s.email = sub1.email
INNER JOIN tb_fees f
ON s.email = f.email AND Sub1.created_on = f.created_on
WHERE s.class = 6
By the way, you probably want indexes on the email fields (or better, use the tb_student id field on the tb_fees table instead of the email field and index it)
Use MAX group function
SELECT s.*, f.amount,MAX(f.created_on)
FROM tb_student s
INNER JOIN
tb_fees f
ON
s.email =f.email
WHERE s.class = 6
GROUP BY s.email

How implementation my wants with MySQL JOIN

_
Hello everyone!
I have table
CREATE TABLE `labels` (
`id` INT NULL AUTO_INCREMENT DEFAULT NULL,
`name` VARCHAR(250) NULL DEFAULT NULL,
`score` INT NULL DEFAULT NULL,
`before_score` INT NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
And I Have This Table
CREATE TABLE `scores` (
`id` INT NULL AUTO_INCREMENT DEFAULT NULL,
`name_id` INT NULL DEFAULT NULL,
`score` INT NULL DEFAULT NULL,
`date` DATETIME DEFAULT NULL,
PRIMARY KEY (`id`)
);
And i want have result where labels.score - have value last scores.score sorted by scores.date and labels.before_score where have value penultimate scores.score sorted by scores.date. Can I do This Only on Mysql slq and how?
Thanks.
ADD
For example i have this data on first table:
INSERT INTO `labels` (id, name, score, before_score) VALUES (1, 'John', 200, 123);
INSERT INTO `labels` (id, name, score, before_score) VALUES (2, 'Eddie', 2000, 2000);
INSERT INTO `labels` (id, name, score, before_score) VALUES (3, 'Bob', 400, 3101);
And second table
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('1','1','12','2013-07-10');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('2','2','2000','2013-05-04');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('3','3','654','2012-09-12');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('4','1','123','2013-12-17');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('5','1','200','2014-04-25');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('6','3','3101','2013-12-02');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('6','2','2000','2015-12-02');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('6','3','400','2013-12-02');
If I understand correctly, you need the last two scores for each name_id.
I would tackle this with temporary tables:
Step 1. Last score:
create temporary table temp_score1
select name_id, max(`date`) as lastDate
from scores
group by name_id;
-- Add the appropriate indexes
alter table temp_score1
add unique index idx_name_id(name_id),
add index idx_lastDate(lastDate);
Step 2. Penultimate score. The idea is exactly the same, but using temp_score1 to filter the data:
create temporary table temp_score2
select s.name_id, max(`date`) as penultimateDate
from scores as s
inner join temp_score1 as t on s.nameId = t.nameId
where s.`date` < t.lastDate
group by name_id;
-- Add the appropriate indexes
alter table temp_score2
add unique index idx_name_id(name_id),
add index idx_penultimateDate(penultimateDate);
Step 3. Put it all together.
select
l.id, l.name,
s1.lastScore, s2.penultimateScore
from
`labels` as l
left join temp_score1 as s1 on l.id = s1.name_id
left join temp_score2 as s2 on l.id = s2.name_id
You can put this three steps inside a stored procedure.
Hope this helps you.