MySQL Group_concat result IN given numbers - mysql

I'm trying to find out, if any number in a group_concat result is in a given set of numbers.
This example data can be used to try it out:
CREATE TABLE `events` (
`eventid` int(11) NOT NULL AUTO_INCREMENT,
`eventname` varchar(255) DEFAULT NULL,
PRIMARY KEY (`eventid`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of `events`
-- ----------------------------
BEGIN;
INSERT INTO `events` VALUES ('1', 'my event');
COMMIT;
-- ----------------------------
-- Table structure for `events2groups`
-- ----------------------------
CREATE TABLE `events2groups` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`eventid` int(11) DEFAULT NULL,
`groupid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of `events2groups`
-- ----------------------------
BEGIN;
INSERT INTO `events2groups` VALUES ('1', '1', '5'), ('2', '1', '3'), ('3', '1', '1');
COMMIT;
-- ----------------------------
-- Table structure for `groups`
-- ----------------------------
CREATE TABLE `groups` (
`groupid` int(11) NOT NULL AUTO_INCREMENT,
`groupname` varchar(255) DEFAULT NULL,
PRIMARY KEY (`groupid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of `groups`
-- ----------------------------
BEGIN;
INSERT INTO `groups` VALUES ('1', 'group1'), ('2', 'group2'), ('3', 'group3'), ('4', 'group4'), ('5', 'group5');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
Then fire this query:
SELECT GROUP_CONCAT(groups.groupid),
IF ( GROUP_CONCAT(groups.groupid) IN (1,2,3), 'yes', 'no' ) as isInGroup
FROM `events`
LEFT JOIN events2groups ON events.eventid = events2groups.eventid
LEFT JOIN groups ON events2groups.groupid = groups.groupid
GROUP BY events.eventid
the first result column shows, that the event has the groups 5, 3 and 1.
The user has the groups 1, 2 and 3, so the 3 and the 1 match. How can I query this to get the 'yes' from the IF?

Why use the group_concat() results? Just use conditional aggregation:
SELECT GROUP_CONCAT(groups.groupid),
(case when max(groups.group_id in (1, 2, 3)) > 0 then 'yes' else 'no'
end) as isInGroup
FROM `events` LEFT JOIN
events2groups
ON events.eventid = events2groups.eventid LEFT JOIN
groups
ON events2groups.groupid = groups.groupid
GROUP BY events.eventid;

SELECT GROUP_CONCAT(groups.groupid),
GROUP_CONCAT(case when groups.groupid IN (1,2,3) then 'yes' else 'no' end) as isInGroup
FROM `events`
LEFT JOIN events2groups ON events.eventid = events2groups.eventid
LEFT JOIN groups ON events2groups.groupid = groups.groupid
GROUP BY events.eventid
;
result
no,yes,yes

Related

MySQL - Remove duplicate records entity relationship many to many

As I can get records from multiple tables omitting duplicate, for example I have this table "code attached tables":
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for interests
-- ----------------------------
DROP TABLE IF EXISTS `interests`;
CREATE TABLE `interests` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of interests
-- ----------------------------
INSERT INTO `interests` VALUES ('1', 'Sport');
INSERT INTO `interests` VALUES ('2', 'Technology');
INSERT INTO `interests` VALUES ('3', 'Games');
INSERT INTO `interests` VALUES ('4', 'Security');
INSERT INTO `interests` VALUES ('5', 'Movies');
-- ----------------------------
-- Table structure for interests_has_user
-- ----------------------------
DROP TABLE IF EXISTS `interests_has_user`;
CREATE TABLE `interests_has_user` (
`interests_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`interests_id`,`user_id`),
KEY `fk_interests_has_user_user1_idx` (`user_id`),
KEY `fk_interests_has_user_interests_idx` (`interests_id`),
CONSTRAINT `fk_interests_has_user_interests` FOREIGN KEY (`interests_id`) REFERENCES `interests` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_interests_has_user_user1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of interests_has_user
-- ----------------------------
INSERT INTO `interests_has_user` VALUES ('1', '1');
INSERT INTO `interests_has_user` VALUES ('2', '1');
INSERT INTO `interests_has_user` VALUES ('3', '1');
INSERT INTO `interests_has_user` VALUES ('4', '1');
INSERT INTO `interests_has_user` VALUES ('5', '1');
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`email` varchar(45) DEFAULT NULL,
`password` varchar(45) DEFAULT NULL,
`country` varchar(45) DEFAULT NULL,
`state` varchar(45) DEFAULT NULL,
`city` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'Name', 'email#email.com', '123123', '1', '1', '1');
I need to get records from the table[ user ] and the table[ interests_has_user ], where a user can have many interests at the table table[ interests_has_user ], I'm doing the query this way:
SELECT
user.id,
user.name,
user.email,
user.country,
user.state,
user.city,
interests_has_user.interests_id,
interests_has_user.user_id
FROM
user
LEFT JOIN interests_has_user
ON user.id = interests_has_user.user_id
WHERE user.id = 1;
And I throw all records of the table table[ interests_has_user ], but in all rows the user is repeated, image attached with the result.
Note: What is shaded in yellow should be empty or null fields.
What the best solution for this, use INNER JOIN, or separate consutas.
I appreciate your help, thank you very much.
INNER JOIN will not return users without interests. So it is not what you want.
If you want to lighten-up the query results you could do two queries:
First find out the user details
SELECT
user.id,
user.name,
user.email,
user.country,
user.state,
user.city
FROM
user
WHERE user.id = 1
Then the interests ids.
SELECT user.id, interests_has_user.interests_id, interests_has_user.user_id
FROM user
LEFT JOIN interests_has_user ON user.id = interests_has_user.user_id
WHERE user.id = 1

MySQL: Select records where joined table matches ALL values

I'm trying to find all employees with multiple skills. Here are the tables:
CREATE TABLE IF NOT EXISTS `Employee` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
INSERT INTO `Employee` (`ID`, `Name`, `Region_ID`) VALUES (1, 'Fred Flintstone'), (2, 'Barney Rubble');
CREATE TABLE IF NOT EXISTS `Skill` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
INSERT INTO `Skill` (`ID`, `Name`) VALUES (1, 'PHP'), (2, 'JQuery');
CREATE TABLE IF NOT EXISTS `Emp_Skills` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`Emp_ID` bigint(20) unsigned NOT NULL DEFAULT '0',
`Skill_ID` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
INSERT INTO `Emp_Skills` (`ID`, `Emp_ID`, `Skill_ID`) VALUES (1, 1, 1), (2, 1, 2), (3, 2, 1);
Here is the query I have so far:
SELECT DISTINCT(em.ID), em.Name
FROM Employee em
INNER JOIN Emp_Skills es ON es.Emp_ID = em.ID
WHERE es.Skill_ID IN ('1', '2')
This returns both employees, however, I need to find the employee that has both skills (ID 1 and 2).
Any ideas? Thanks
This will do it:
SELECT EmpId, Name
FROM
(
SELECT em.ID as EmpId, em.Name, es.ID as SkillID
FROM Employee em
INNER JOIN Emp_Skills es ON es.Emp_ID = em.ID
WHERE es.Skill_ID IN ('1', '2')
) X
GROUP BY EmpID, Name
HAVING COUNT(DISTINCT SkillID) = 2;
Fiddle here:
The distinct is just in case the same employee has the skill listed twice.
Thanks for the test data.
You can do this with aggregation and a having clause:
SELECT em.ID, em.Name
FROM Employee em INNER JOIN
Emp_Skills es
ON es.Emp_ID = em.ID
GROUP BY em.id, em.name
HAVING sum(es.Skill_id = '1') > 0 and
sum(es.Skill_id = '2') > 0;
Each condition in the having clause counts the number of rows for each employee that have a particular skill. The filter guarantees that both skills are present.

how to get vistors_sum and reviews_count in 3 table?

how to get vistors_sum and reviews_count in 3 table ?
see the bellow codes, how to get my result in one sql?
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `a`
-- ----------------------------
DROP TABLE IF EXISTS `a`;
CREATE TABLE `a` (
`products_id` int(11) NOT NULL,
`products_name` varchar(255) default NULL,
PRIMARY KEY (`products_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of a
-- ----------------------------
INSERT INTO `a` VALUES ('1', 'jimmy');
INSERT INTO `a` VALUES ('2', 'tina');
INSERT INTO `a` VALUES ('3', 'emma');
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `b`
-- ----------------------------
DROP TABLE IF EXISTS `b`;
CREATE TABLE `b` (
`id` int(11) NOT NULL auto_increment,
`products_id` int(11) NOT NULL,
`vistors` int(11) NOT NULL,
`date` date default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of b
-- ----------------------------
INSERT INTO `b` VALUES ('1', '1', '1', '2013-11-13');
INSERT INTO `b` VALUES ('2', '1', '2', '2013-11-04');
INSERT INTO `b` VALUES ('3', '2', '1', '2013-11-13');
INSERT INTO `b` VALUES ('4', '2', '3', '2013-11-13');
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `c`
-- ----------------------------
DROP TABLE IF EXISTS `c`;
CREATE TABLE `c` (
`id` int(11) NOT NULL auto_increment,
`products_id` int(11) NOT NULL,
`review_content` varchar(255) default NULL,
`date` date default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of c
-- ----------------------------
INSERT INTO `c` VALUES ('1', '1', 'hello', '2013-11-13');
INSERT INTO `c` VALUES ('2', '1', 'world', '2013-11-13');
INSERT INTO `c` VALUES ('3', '2', 'good', '2013-11-12');
INSERT INTO `c` VALUES ('4', '3', 'boy', '2013-11-13');
this code bellow can do but the date condition is in sub children temp table. this make the sql not flexible (if I want to query any time not 2013-11-13)
select
a.products_id,
a.products_name,
b.vistors_sum,
c.reviews_count
from
a
left join
(
select
b.products_id,
b.date,
sum(b.vistors) as vistors_sum
from b
where b.date = '2013-11-13'
group by b.products_id
) as b on a.products_id = b.products_id
left join
(
select
c.products_id,
count(c.products_id) as reviews_count
from c
where c.date = '2013-11-13'
group by c.products_id
) as c on a.products_id = c.products_id
SQLFiddle demo
select a.products_id,
products_name,
COALESCE(b.sum_visitors,0) as sum_visitors,
COALESCE(c.count_comments,0) as count_comments
from a
left join
( SELECT products_id,sum(vistors) as sum_visitors
FROM b
WHERE date='2013-11-13'
GROUP BY products_id
) as b
on (a.products_id=b.products_id)
left join
(
SELECT products_id,count(*) as count_comments
FROM c
WHERE date='2013-11-13'
GROUP BY products_id
) as c
on (a.products_id=c.products_id)

Showing all categories for every product for which it belongs to in one query

how can i get the result as bellow in mysql?
I want to get all products group by id and show what categories it belongs to.
how can I get it in one sql ?
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `a`
-- ----------------------------
DROP TABLE IF EXISTS `a`;
CREATE TABLE `a` (
`products_id` int(11) NOT NULL,
`products_name` varchar(255) default NULL,
PRIMARY KEY (`products_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of a
-- ----------------------------
INSERT INTO `a` VALUES ('1', 'hello');
INSERT INTO `a` VALUES ('2', 'world');
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `b`
-- ----------------------------
DROP TABLE IF EXISTS `b`;
CREATE TABLE `b` (
`products_id` int(11) NOT NULL,
`categories_id` int(11) NOT NULL,
PRIMARY KEY (`products_id`,`categories_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of b
-- ----------------------------
INSERT INTO `b` VALUES ('1', '1');
INSERT INTO `b` VALUES ('1', '2');
INSERT INTO `b` VALUES ('2', '1');
INSERT INTO `b` VALUES ('2', '3');
This is what you want?
SELECT a.products_id, a.products_name,
GROUP_CONCAT(CONVERT(b.categories_id,CHAR(8))) as products_to_categories
FROM a,b
WHERE a.products_id = b.products_id
GROUP BY a.products_id, a.products_name
fiddle at http://www.sqlfiddle.com/#!2/39edfc/3/0
Resulting image in fiddle
there are alternative way by using inner join, cheer =)
SELECT a.products_id, a.products_name,group_concat(b.categories_id)
FROM a
INNER JOIN b ON a.products_id = b.products_id
group by a.products_id, a.products_name

How do I best combine and optimize these two queries?

Here is my main query which pulls in thread information as one row, it lacks the # of votes and currently I'm pulling that in with a second query.
SELECT Group_concat(t.tag_name) AS `tags`,
`p`.`thread_id`,
`p`.`thread_name`,
`p`.`thread_description`,
`p`.`thread_owner_id`,
`p`.`thread_view_count`,
`p`.`thread_reply_count`,
`p`.`thread_comment_count`,
`p`.`thread_favorite_count`,
`p`.`thread_creation_date`,
`p`.`thread_type_id`,
`p`.`thread_edited_date`,
`u`.*,
`x`.*,
`t`.*
FROM `shoop_posts` AS `p`
INNER JOIN `shoop_users` AS `u`
ON u.user_id = p.thread_owner_id
LEFT JOIN `shoop_tags_map` AS `x`
ON x.thread_id = p.thread_id
LEFT JOIN `shoop_tags` AS `t`
ON t.tag_id = x.tag_id
WHERE (p.thread_id = '1')
GROUP BY `p`.`thread_id`
My second query which pulls in the # of votes per thread:
SELECT Sum(vote_value)
FROM shoop_votes
INNER JOIN shoop_vote_codes
ON shoop_votes.vote_type = shoop_vote_codes.vote_type
WHERE thread_id = 1
AND shoop_votes.vote_type = 3
OR shoop_votes.vote_type = 2
A vote type of 2 is an upvote, 3 is a downvote. Here's the schema if you need it, and some sample data:
CREATE TABLE `shoop_posts` (
`thread_id` int(11) unsigned NOT NULL auto_increment,
`thread_name` text,
`thread_description` text,
`thread_parent_id` int(11) default NULL,
`thread_owner_id` int(11) default NULL,
`thread_view_count` int(11) default NULL,
`thread_reply_count` int(11) default NULL,
`thread_comment_count` int(11) default NULL,
`thread_favorite_count` int(11) default NULL,
`thread_creation_date` timestamp NULL default NULL,
`thread_type_id` int(11) default NULL,
`thread_edited_date` timestamp NULL default NULL,
PRIMARY KEY (`thread_id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of shoop_posts
-- ----------------------------
INSERT INTO `shoop_posts` VALUES ('1', 'Shoop that', '\r\n<img class=\"image-shoop\" src=\"\">\r\n\r\n<p>test:<br>\r\n\r\n\r\n</p>', null, '2', '217', '0', '0', '0', '2010-01-10 02:06:25', '1', null);
-- ----------------------------
-- Table structure for `shoop_tags`
-- ----------------------------
CREATE TABLE `shoop_tags` (
`tag_id` int(11) NOT NULL auto_increment,
`tag_name` varchar(11) default NULL,
PRIMARY KEY (`tag_id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of shoop_tags
-- ----------------------------
INSERT INTO `shoop_tags` VALUES ('1', 'mma');
INSERT INTO `shoop_tags` VALUES ('2', 'strikeforce');
INSERT INTO `shoop_tags` VALUES ('3', 'ufc');
-- ----------------------------
-- Table structure for `shoop_tags_map`
-- ----------------------------
DROP TABLE IF EXISTS `shoop_tags_map`;
CREATE TABLE `shoop_tags_map` (
`map_id` int(11) NOT NULL auto_increment,
`tag_id` int(11) default NULL,
`thread_id` int(11) default NULL,
PRIMARY KEY (`map_id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of shoop_tags_map
-- ----------------------------
INSERT INTO `shoop_tags_map` VALUES ('1', '1', '1');
INSERT INTO `shoop_tags_map` VALUES ('2', '2', '2');
INSERT INTO `shoop_tags_map` VALUES ('3', '1', '2');
INSERT INTO `shoop_tags_map` VALUES ('4', '3', '1');
INSERT INTO `shoop_tags_map` VALUES ('5', '3', '2');
-- ----------------------------
-- Table structure for `shoop_vote_codes`
-- ----------------------------
CREATE TABLE `shoop_vote_codes` (
`vote_type` smallint(1) NOT NULL default '0',
`vote_value` smallint(2) default NULL,
PRIMARY KEY (`vote_type`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of shoop_vote_codes
-- ----------------------------
INSERT INTO `shoop_vote_codes` VALUES ('2', '1');
INSERT INTO `shoop_vote_codes` VALUES ('3', '-1');
-- ----------------------------
-- Table structure for `shoop_votes`
-- ----------------------------
DROP TABLE IF EXISTS `shoop_votes`;
CREATE TABLE `shoop_votes` (
`thread_id` int(11) NOT NULL default '0',
`user_id` int(11) NOT NULL default '0',
`vote_type` smallint(1) NOT NULL default '0',
PRIMARY KEY (`thread_id`,`user_id`,`vote_type`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of shoop_votes
-- ----------------------------
INSERT INTO `shoop_votes` VALUES ('1', '1', '2');
INSERT INTO `shoop_votes` VALUES ('1', '2', '2');
INSERT INTO `shoop_votes` VALUES ('1', '3', '3');
If I understand you correctly, just using a subquery will do what you're after:
SELECT Group_concat(t.tag_name) AS `tags`,
`p`.`thread_id`,
`p`.`thread_name`,
`p`.`thread_description`,
`p`.`thread_owner_id`,
`p`.`thread_view_count`,
`p`.`thread_reply_count`,
`p`.`thread_comment_count`,
`p`.`thread_favorite_count`,
`p`.`thread_creation_date`,
`p`.`thread_type_id`,
`p`.`thread_edited_date`,
`u`.*,
`x`.*,
`t`.*,
`v`.VoteTotal
FROM `shoop_posts` AS `p`
INNER JOIN `shoop_users` AS `u`
ON u.user_id = p.thread_owner_id
LEFT JOIN `shoop_tags_map` AS `x`
ON x.thread_id = p.thread_id
LEFT JOIN `shoop_tags` AS `t`
ON t.tag_id = x.tag_id
LEFT JOIN (SELECT thread_id, Sum(vote_value) as VoteTotal
FROM shoop_votes
INNER JOIN shoop_vote_codes
ON shoop_votes.vote_type = shoop_vote_codes.vote_type
WHERE shoop_votes.vote_type = 3
OR shoop_votes.vote_type = 2
GROUP BY thread_id) as `v`
ON p.thread_id = v.thread_id
WHERE (p.thread_id = '1')
GROUP BY `p`.`thread_id`
This will let you get all threads as well if you just leave off where last where p.thread_id clause.