How to SELECT with the given tables? - mysql

CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(16) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `permissions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`description` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `user_permissions` (
`user_id` int(11) DEFAULT NULL,
`permission_id` int(11) DEFAULT NULL,
KEY `user_id_fk` (`user_id`),
KEY `permission_id_fk` (`permission_id`),
CONSTRAINT `permission_id_fk` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`),
CONSTRAINT `user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
);
Given the above tables, how can I perform a SELECT that will return <users.name> | <true / false> if a specific user.id has permissions.id 1, 2, 3 and 4 based on the user_permissions n:m table?
Something like:
SELECT users.name, (..something..) as valid FROM user_permissions WHERE users.id 1 has 1,2,3 and 4 permissions

You need a left join of users to user_permissions, group by user and conditional aggregation:
select
u.id, u.name,
case count(up.permission_id)
when 4 then 'true'
else 'false'
end result
from users u left join user_permissions up
on up.user_id = u.id and up.permission_id in (1, 2, 3, 4)
group by u.id, u.name

Related

mysql view users vs admin users syntax inquiry

Setting up JDBC security realm with Glassfish and I came across this link that provides user control access (admin vs view users). here is the link for this tutorial.
http://jugojava.blogspot.com.eg/2011/02/jdbc-security-realm-with-glassfish-and.html?showComment=1459000091065#c232448315667617784
Few things I didn't understand in the guide and I hope if you can help. What do the lines below mean? (full sql code at the end of of the question)
KEY `fk_users_has_groups_groups1` (`group_id`),
KEY `fk_users_has_groups_users` (`user_id`),
I don't see any table named u but the code is using u.*. The code at the very bottom doesn't have "u" table in it. However, I see the reference to "u" in the inner Join. Can I do select u. based on this INNER JOIN?
CREATE VIEW `v_user_role` AS
SELECT u.username, u.password, g.group_name
FROM `user_groups` ug
INNER JOIN `users` u ON u.user_id = ug.user_id
INNER JOIN `groups` g ON g.group_id = ug.group_id;
Here is the full Code
CREATE TABLE `groups` (
`group_id` int(10) NOT NULL,
`group_name` varchar(20) NOT NULL,
`group_desc` varchar(200) DEFAULT NULL,
PRIMARY KEY (`group_id`)
);
CREATE TABLE `users` (
`user_id` int(10) NOT NULL AUTO_INCREMENT,
`username` varchar(10) NOT NULL,
`first_name` varchar(20) DEFAULT NULL,
`middle_name` varchar(20) DEFAULT NULL,
`last_name` varchar(20) DEFAULT NULL,
`password` char(32) NOT NULL,
PRIMARY KEY (`user_id`)
);
CREATE TABLE `user_groups` (
`user_id` int(10) NOT NULL,
`group_id` int(10) NOT NULL,
PRIMARY KEY (`user_id`,`group_id`),
KEY `fk_users_has_groups_groups1` (`group_id`),
KEY `fk_users_has_groups_users` (`user_id`),
CONSTRAINT `fk_groups` FOREIGN KEY (`group_id`) REFERENCES `groups` (`group_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_users` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
);
CREATE VIEW `v_user_role` AS
SELECT u.username, u.password, g.group_name
FROM `user_groups` ug
INNER JOIN `users` u ON u.user_id = ug.user_id
INNER JOIN `groups` g ON g.group_id = ug.group_id;
INSERT INTO `groups`(`group_id`,`group_name`,`group_desc`) VALUES
(1,'USER','Regular users'),
(2,'ADMIN','Administration users');
INSERT INTO `users`(`user_id`,`username`,`first_name`,`middle_name`,`last_name`,`password`) VALUES
(1,'john','John',NULL,'Doe','6e0b7076126a29d5dfcbd54835387b7b'), /*john123*/
(2,'admin',NULL,NULL,NULL,'21232f297a57a5a743894a0e4a801fc3'); /*admin*/
INSERT INTO `user_groups`(`user_id`,`group_id`) VALUES (1,1),(2,1),(2,2);
1) KEY indicates that those fields are indexed. The index is not unique. See create index documentation.
2) The "u" is an alias, specifically it is a table alias. You can use aliases to refer to a table or field name under a different name. An alias is specific to a query. The alias is defined in the from clause:
`users` u

Generate Prefix Number ID with Condition By Group ID

First this is my table
CREATE TABLE IF NOT EXISTS `group` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `member` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`group_id` int(11) unsigned NOT NULL,
`code` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `group_id` (`group_id`),
FOREIGN KEY (`group_id`) REFERENCES `group` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I need member.id look like 001, 002, 003. . i following lpad(id, 3, 0) and case close
But how to reset 001, 002, 003 back to 001 again where have different group_id
This query have result 01-001, 01-002, 02-003, 03-004 (group.id - member.id)
SELECT CONCAT(lpad(g.id, 2, 0),'-',lpad(m.id, 3, 0)) AS id, m.name
FROM member m
LEFT JOIN group g ON g.id = m.group_id
ORDER BY m.id ASC
Please help, i need 01-001, 01-002, 02-001, 03-001 (group.id - member.id)
Or can i use trigger to make my member.code auto generate when insert to 01-001, 01-002, 02-003, 03-004 base on group.id - member.id

mysql select from one to many relation

I have two tables - Users and Products. User may have a few products. I need to select all products and show which user they belong.
How to solve it using mysql joins.
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`login` varchar(16) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8
CREATE TABLE `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`description` varchar(255) NOT NULL,
`price` decimal(10,2) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
CONSTRAINT `user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8
I've tried like this:
SELECT users.login FROM users LEFT JOIN products ON users.id=products.user_id;
But in this case it shows me only user logins, but i need to get product name, price and description as well.
SELECT p.name, p.price, p.description, group_concat(u.login) as users
FROM products p
LEFT JOIN users u ON u.id = p.user_id
GROUP BY p.name, p.price, p.description

complex sql query comparing data and creating a list

I've users table:
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`email` char(255) NOT NULL DEFAULT '',
`password` char(12) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
books table:
CREATE TABLE `books` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`book` char(55) NOT NULL DEFAULT '',
`user_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `book` (`book`),
KEY `user_id` (`user_id`),
CONSTRAINT `books_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And read table:
CREATE TABLE `read` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) unsigned NOT NULL,
`book_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `No duplicates` (`user_id`,`book_id`),
KEY `book_id` (`book_id`),
CONSTRAINT `connections_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `connections_ibfk_2` FOREIGN KEY (`book_id`) REFERENCES `books` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I'd like for user_id = 1, to create list of other user_id's - matching point is the common books they have read. So if user_id = 1 and user_id = 2 have in common 5 books then user_id should be on that list. I'm not so good at sql, so any recommendation on how to achieve this, even little optimisation tip will be much appreciated.
Possible solution - gives users that read 5 or more common books
SELECT r2.user_id
FROM `read` r1
JOIN `read` r2
ON r1.user_id <> r2.user_id AND r1.book_id = r2.book_id
WHERE r1.user_id = 1
GROUP BY r2.user_id
HAVING count(*) >= 5
If users must have exactly 5 common books (no less and no more), a clause with HAVING must be changed into:
HAVING count(*) = 5
Demo: --> http://www.sqlfiddle.com/#!2/7a9b7/1
A simple change to the query gives pairs of users that read >= 5 common books:
SELECT r1.user_id user1, r2.user_id user2
FROM `read` r1
JOIN `read` r2
ON r1.user_id < r2.user_id AND r1.book_id = r2.book_id
-- WHERE r1.user_id = 1
GROUP BY r1.user_id, r2.user_id
HAVING count(*) >= 5;
Demo: --> http://www.sqlfiddle.com/#!2/7a9b7/3
---- EDIT ----
To order users by number of matches use this query:
SELECT r1.user_id user1, r2.user_id user2,
count(*) number_of_matches
FROM `read` r1
JOIN `read` r2
ON r1.user_id < r2.user_id AND r1.book_id = r2.book_id
-- WHERE r1.user_id = 1
GROUP BY r1.user_id, r2.user_id
HAVING count(*) >= 5
ORDER BY number_of_matches DESC
-- you may also use:
-- ORDER BY COUNT(*) DESC
;
demo --> http://www.sqlfiddle.com/#!2/7a9b7/8

Joining 3+ tables using SQL displaying too many results

im trying to create a query to join these tables together using this method below. However it is repeating results and they are not linking up correctly. as in the same rating comment would be on about 4/5 different results etc. its producing 18ish results when im expecting 3. would anyone be willing to help me with this problem?
SELECT a.Company_name,
f.Job_ID,
f.Job_Name,
b.User_Name,
c.Comments,
c.Reliability,
c.Rating
FROM company a,
Users b,
Ratings c,
UserCompJobRating d,
Company_Job e,
Jobs f
WHERE d.Comp_job_ID = e.Comp_Job_ID
AND b.users_ID = d.users_ID
AND c.Rating_ID = d.Rating_ID;
Many Thanks,
Andrew
ok i tried this and it is saying e.Users_ID is an unknown column in 'on clause'
SELECT a.Company_name,
b.Job_ID,
b.Job_Name,
c.User_Name,
d.Comments,
d.Reliability,
d.Rating
FROM Company a, UserCompJobRating e, Jobs b
INNER JOIN Users c
ON c.Users_ID = e.Users_ID
inner join Company_Job f
on e.Comp_Job_ID = f.Comp_Job_ID
inner join Ratings d
on d.Rating_ID = e.Rating_ID;
I'm assuming im close, however way off at the same time?
Ill try to give you some more information:
UserCompJobRating has a primary key UCJR_ID and 3 foreign keys of Comp_Job_ID, Users_ID and Rating_ID
Company_Job table as a primary key Comp_Job_ID, and 2 foreign keys Job_ID, Company_ID
Ratings Table has just the Rating_ID as a primary key and the rest just to do with the rating information
Users Table has a Users_ID as a primary key and basic user information address etc etc
Jobs Table has a Job_ID primary key and basic information about the job, such as name, price, etc.
Company Table has Company_ID as a primary key and the basic company information, similar to the Users table.
Here are the definations:
CREATE TABLE `company` (
`Company_ID` int(11) NOT NULL AUTO_INCREMENT,
`Company_Name` varchar(45) NOT NULL,
`CAddress` varchar(45) NOT NULL,
`CTown` varchar(45) NOT NULL,
`CPostcode` varchar(12) NOT NULL,
`CTelephone` varchar(45) NOT NULL,
PRIMARY KEY (`Company_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
CREATE TABLE `company_job` (
`Comp_Job_ID` int(11) NOT NULL AUTO_INCREMENT,
`Company_ID` int(11) NOT NULL,
`Job_ID` int(11) NOT NULL,
PRIMARY KEY (`Comp_Job_ID`),
KEY `Company_ID_idx` (`Company_ID`),
KEY `Job_ID_idx` (`Job_ID`),
CONSTRAINT `Company_ID` FOREIGN KEY (`Company_ID`) REFERENCES `company` (`Company_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `Job_ID` FOREIGN KEY (`Job_ID`) REFERENCES `jobs` (`Job_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
CREATE TABLE `jobs` (
`Job_ID` int(11) NOT NULL AUTO_INCREMENT,
`Job_Name` varchar(45) NOT NULL,
`Job_Cost` varchar(45) DEFAULT NULL,
`Job_Avg_Time` varchar(45) DEFAULT NULL,
`Job_Avg_Cost` varchar(45) DEFAULT NULL,
`Job_Description` varchar(45) NOT NULL,
`Company_ID` int(11) NOT NULL,
PRIMARY KEY (`Job_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `ratings` (
`Rating_ID` int(11) NOT NULL AUTO_INCREMENT,
`Comments` varchar(200) DEFAULT NULL,
`Cost` varchar(45) DEFAULT NULL,
`Reliability` varchar(45) DEFAULT NULL,
`Rating` int(11) DEFAULT NULL,
PRIMARY KEY (`Rating_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `usercompjobrating` (
`UCJR_ID` int(11) NOT NULL AUTO_INCREMENT,
`Comp_Job_ID` int(11) DEFAULT NULL,
`Rating_ID` int(11) DEFAULT NULL,
`Users_ID` int(11) DEFAULT NULL,
PRIMARY KEY (`UCJR_ID`),
KEY `Comp_Job_ID_idx` (`Comp_Job_ID`),
KEY `Rating_ID_idx` (`Rating_ID`),
KEY `User_ID_idx` (`Users_ID`),
CONSTRAINT `Comp_Job_ID` FOREIGN KEY (`Comp_Job_ID`) REFERENCES `company_job` (`Comp_Job_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `Rating_ID` FOREIGN KEY (`Rating_ID`) REFERENCES `ratings` (`Rating_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `Users_ID` FOREIGN KEY (`Users_ID`) REFERENCES `users` (`Users_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `users` (
`Users_id` int(11) NOT NULL AUTO_INCREMENT,
`User_Name` varchar(45) NOT NULL,
`UAddress` varchar(45) NOT NULL,
`UTown` varchar(45) NOT NULL,
`UPostcode` varchar(45) NOT NULL,
`UTelephone` varchar(45) NOT NULL,
`UDOB` varchar(45) NOT NULL,
PRIMARY KEY (`Users_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
The query needs to look something like this i.e. use this form
SELECT a.Company_name,
f.Job_ID,
f.Job_Name,
b.User_Name,
c.Comments,
c.Reliability,
c.Rating
FROM company a
INNER JOIN Users b
ON a.???? = b.???
Since I dont have your table definitions I cant help you with the JOIN conditions. Show us the tables definition and we would be able to help.
UPDATE:
So based on your table structures you will be looking for something like this:
SELECT *
FROM company cmp
INNER JOIN company_job cmpjb
ON cmp.Company_ID = cmpjb.Company_ID
INNER JOIN jobs jb
ON cmpjb.Job_ID = jb.Job_ID
INNER JOIN usercompjobrating ucmpjbr
ON ucmpjbr.Comp_Job_ID = ucmpjbr.Comp_Job_ID
INNER JOIN users usr
ON usr.Users_id = ucmpjbr.Users_ID
INNER JOIN ratings rat
ON rat.Rating_ID = ucmpjbr.Rating_ID
Note you cannot use the folder table in this join as there are no primary/foreign key relationships to any of the other tables from the folder table.
I would suggest that you carefully dissect this query and let me know if you need to understand the details.
One thing to clarify, what is company_id in table jobs?
select ... (necessary fields to select)
from company c
join company_job cj using (company_id)
join jobs j using (job_id)
join usercompjobrating ucjr using (comp_job_id)
join ratings using (rating_Id)
join users using (users_id)