Mysql query generation - mysql

This is my user table schema
CREATE TABLE IF NOT EXISTS `ehobe_user` (
`user_id` bigint(20) NOT NULL,
`user_email` varchar(80) NOT NULL,
`user_password` varchar(50) NOT NULL,
`user_fname` varchar(255) NOT NULL,
`user_lname` varchar(255) NOT NULL,
`user_terms` enum('yes','no') NOT NULL DEFAULT 'yes',
`is_active` enum('yes','no') NOT NULL DEFAULT 'yes',
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
And this is my friends table schema
CREATE TABLE IF NOT EXISTS `ehobe_friends` (
`user_id1` bigint(20) NOT NULL,
`user_id2` bigint(20) NOT NULL,
`relationship_id` int(1) NOT NULL COMMENT '1 - user1 request, 2- user2 request, 3 - friends, 4- user1 blocked, 5 - user2 blocked'
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
So i need to select the user first name and last name who are my frinds in the friends table.

Suppose you want friends of USER_ID #67.
Try:
select u.user_id, u.user_fname, u.user_lname
from ehobe_user u
inner join ehobe_friends f1 on (u.user_id = f1.user_id1)
where f1.user_id2 = 67
union
select u.user_id, u.user_fname, u.user_lname
from ehobe_user u
inner join ehobe_friends f2 on (u.user_id = f2.user_id2)
where f2.user_id1 = 67

Logically, you want to get all of the friends in an array and check each user for matching info. I would give you code, but I don't know what language you're writing this in.

Related

MySQL performance with nested sub query

I have two tables messages and members. I tried joining tables without having a nested query but it does not reflect the join on members. So, I initially thought that I could do the following
SELECT M1.*, COUNT(M2.emid) AS replies FROM messages M1
LEFT JOIN messages M2
ON M2.thread = M1.emid
INNER JOIN members M
ON M.meid = M1.emitter
WHERE
M1.thread is NULL AND
M1.receiver = 2
GROUP BY
M1.emid
but it does not seem to join the corresponding member. Then I tried this and it gives me the result that I need but I would like to know if there is a way to accomplish the same result using joins without the nested query
SELECT * FROM (
SELECT M1.*, COUNT(M2.emid) AS replies FROM messages M1
LEFT JOIN messages M2
ON M2.thread = M1.emid
WHERE
M1.thread is NULL AND
M1.receiver = 2
GROUP BY
M1.emid
) O INNER JOIN members M ON O.receiver = M.meid
-- Table structure for table members
CREATE TABLE `members` (
`meid` bigint(64) NOT NULL,
`name` varchar(32) DEFAULT NULL,
`lastname` varchar(32) DEFAULT NULL,
`email` varchar(128) NOT NULL,
`mobile` char(10) DEFAULT NULL,
`college` bigint(64) NOT NULL,
`major` bigint(64) NOT NULL,
`password` varchar(256) NOT NULL,
`oauth` varchar(128) DEFAULT NULL,
`confirmed` tinyint(4) DEFAULT NULL,
`active` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`joined` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- Table structure for table messages
CREATE TABLE `messages` (
`emid` bigint(20) NOT NULL,
`emitter` bigint(20) NOT NULL,
`receiver` bigint(20) NOT NULL,
`thread` bigint(20) DEFAULT NULL,
`opened` tinyint(4) DEFAULT '0',
`message` blob NOT NULL,
`timecard` datetime DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Mysql case when getting another table

I have got two tables one is log details and another is user name list.
I can get with "INNER JOIN user_tbl ON log_user_id=user_id" but also I have got a super user id is exception and this exception user isn't in the user table. I am using this user at the back ground the relation with database is level of this user like as 9999.
How can I show the super user as a name like as "Supervisory"?
Example sql:
Table structures are:
CREATE TABLE `user_list_tb` (
`user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_name` varchar(40) COLLATE utf8_turkish_ci NOT NULL,
`user_pwd` varchar(40) COLLATE utf8_turkish_ci NOT NULL,
`user_level` int(11) NOT NULL DEFAULT '0',
`user_owner_id` int(10) unsigned NOT NULL,
`user_datetime` datetime NOT NULL,
`user_change_pwd` tinyint(1) DEFAULT NULL,
`user_pwd_try` int(3) unsigned DEFAULT NULL,
PRIMARY KEY (`user_id`),
UNIQUE KEY `user_name_UNIQUE` (`user_name`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci;
CREATE TABLE `log_system_tb` (
`log_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`log_act_name` varchar(10) COLLATE utf8_turkish_ci NOT NULL,
`log_user_id` int(10) unsigned NOT NULL,
`log_datetime` datetime NOT NULL,
`log_message` varchar(256) COLLATE utf8_turkish_ci DEFAULT NULL,
PRIMARY KEY (`log_id`)
) ENGINE=InnoDB AUTO_INCREMENT=49720 DEFAULT CHARSET=utf8 COLLATE=utf8_turkish_ci;
SELECT
log_id,
log_act_name,
log_user_id,
user_name,
log_datetime,
log_message
from log_system_tb
JOIN user_list_tb
ON (log_user_id=user_id)
where log_datetime>="2016-04-01 00:00:00"
and
log_datetime<="2016-04-14 00:00:00"
order by log_id desc limit 1000;
Best regards
Mehmet
You need to use a left join because there will not be a row in the user_list that corresponds to the supervisor's logged events. Also please see the case statement below.
SELECT
log_id,
log_act_name,
log_user_id,
(case when user_id=9999 then 'Supervisory' ELSE user_name END),
log_datetime,
log_message
from log_system_tb
LEFT JOIN user_list_tb
ON (log_user_id=user_id)
where log_datetime>="2016-04-01 00:00:00"
and
log_datetime<="2016-04-14 00:00:00"
order by log_id desc limit 1000;
You can do it like this:
(case when user_id=9999 then 'Supervisory' END)

How do I join 2 columns in MySql?

I have the following table structure in my code and I am trying to pull username and name fields from users table, but the query currently pulls only from_user_id data. How do I modify this so that I get two separate columns that lists username and name for both to_user_id and from_user_id?
SELECT f.id, from_user_id, to_user_id, STATUS, u.username, u.name
FROM friend f
left JOIN users u ON f.from_user_id = u.id
WHERE f.id IN(
SELECT source_id
FROM notification
WHERE user_id = 5 AND notification_read = 1)
users table:
CREATE TABLE `users` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(60) NOT NULL,
`password` VARCHAR(64) NOT NULL,
`enabled` TINYINT(4) NOT NULL DEFAULT '1',
`email` VARCHAR(100) NOT NULL,
`name` VARCHAR(100) NOT NULL,
`created_on` DATETIME NOT NULL,
`role` VARCHAR(50) NULL DEFAULT 'ROLE_USER',
PRIMARY KEY (`id`),
UNIQUE INDEX `username` (`username`)
)
and friend table:
CREATE TABLE `friend` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`from_user_id` BIGINT(20) NOT NULL,
`to_user_id` BIGINT(20) NOT NULL,
`status` INT(2) NOT NULL,
`requested_date` DATETIME NULL DEFAULT NULL,
`accepted_date` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `from_user_id` (`from_user_id`),
INDEX `to_user_id` (`to_user_id`)
)
and a notification table:
CREATE TABLE `notification` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`user_id` BIGINT(20) NOT NULL,
`activity_type` TINYINT(4) NOT NULL,
`source_id` BIGINT(20) NOT NULL,
`parent_id` BIGINT(20) NULL DEFAULT NULL,
`parent_type` TINYINT(4) NULL DEFAULT NULL,
`notification_read` TINYINT(4) NOT NULL DEFAULT '0',
`created_on` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `user_id` (`user_id`),
INDEX `created_on` (`created_on`)
)
You need to perform two joins against users - one for each side of the friend relationship, and include the appropriate columns in the SELECT list from both of those joins against users.
SELECT
f.id,
from_user_id,
to_user_id,
STATUS,
-- uf is an alias for the "from" user
-- You must alias the columns to distinguish them
uf.username AS from_username,
uf.name AS from_name,
-- ut is an alias for the "to" user
ut.username AS to_username,
ut.name AS to_name
FROM
friend f
-- Join first for the from user info
LEFT JOIN users uf ON f.from_user_id = uf.id
-- Join again for the to user info
LEFT JOIN users ut ON f.to_user_id = ut.id
WHERE f.id IN(
SELECT source_id
FROM notification
WHERE user_id = 5 AND notification_read = 1
)
A further note... You can substitute an INNER JOIN against notification instead of the IN () subquery, and you may achieve better performance.
SELECT
DISTINCT /* needed assuming multiple notification.source_id per f.id */
f.id,
from_user_id,
to_user_id,
STATUS,
uf.username AS from_username,
uf.name AS from_name,
ut.username AS to_username,
ut.name AS to_name
FROM
friend f
LEFT JOIN users uf ON f.from_user_id = uf.id
LEFT JOIN users ut ON f.to_user_id = ut.id
-- Join notification instead of the IN () subquery
INNER JOIN notification
ON f.id = notification.source_id
AND notification.user_id = 5
AND notification_read = 1

how to create a team leaderboard with info from 4 tables?

This is tricky, I have been tasked with creating an team leader board where individuals complete tasks for a score. The score is defined in the table "station" and every time a user completes a task- a post is created in the posts table with the id of the station and their RFID (radio frequency ID). There is a team table which defines the team name.
i need a way to get the sum of all the post scores (joined points from stations table) a teams members have participated in.
The result should be sorted be team score and look something like if we have 4 teams with 4 members who participated in 4 events- whats the total score for each team
Team name one (Teams.name) | score
Team name two (Teams.name) | score
Team name three (Teams.name) | score
The tables -
CREATE TABLE `posts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rfid` varchar(50) NOT NULL,
`station_id` int(11) NOT NULL,
`updated_at` datetime NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
-- --------------------------------------------------------
Table structure for table stations
CREATE TABLE `stations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`description` text NOT NULL,
`points` int(11) NOT NULL,
`logic` varchar(200) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1023 ;
-- --------------------------------------------------------
Table structure for table teams
CREATE TABLE `teams` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
-- --------------------------------------------------------
Table structure for table users
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rfid` varchar(50) NOT NULL,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`team` int(11) NOT NULL,
`quiz_score` int(11) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
I have created an query for an individual leaderboard-
SELECT users.first_name, users.last_name, posts.rfid, sum(stations.points) score
FROM posts
JOIN users ON posts.rfid = users.rfid
JOIN stations ON posts.station_id = stations.id
GROUP BY posts.rfid
ORDER BY score DESC LIMIT 0 , 100
this is what i have got so far for the team one
SELECT name, (SELECT sum(stations.points) score FROM posts
JOIN users ON posts.rfid = users.rfid
JOIN stations ON posts.station_id = stations.id
WHERE users.team = teams.id
GROUP BY posts.rfid) team_score FROM teams
//subquery returns more than one row
I think this might be the correct answer
SELECT name,
(SELECT sum(stations.points) score FROM posts
JOIN users ON posts.rfid = users.rfid
JOIN stations ON posts.station_id = stations.id
WHERE users.team = teams.id ) team_score
FROM teams

Help with a MySQL query

I have the following query:
SELECT u.uid, pf.title, pv.value FROM users AS u INNER JOIN
profile_values AS pv ON pv.uid = u.uid
INNER JOIN
profile_fields AS pf ON pf.fid = pv.fid
ORDER BY u.uid
Which results in:
uid title value
1 First name Jared
1 Last name Boo
1 Organization Acme
1 Website http://acme.com
1 Country Canada
6 First name Nathan
6 Last name Foo
I am attempting to use this result to create another result set which looks like this:
uid First name Last name Organization Website Country
1 Jared Boo Acme http... Canada
6 Nathan Foo
Am I going about this correctly?
Thanks in advance
EDIT
Tables:
CREATE TABLE `users` (
`uid` int(10) unsigned NOT NULL auto_increment,
`name` varchar(60) NOT NULL default '',
`pass` varchar(32) NOT NULL default '',
`mail` varchar(64) default '',
`created` int(11) NOT NULL default '0',
`access` int(11) NOT NULL default '0',
PRIMARY KEY (`uid`),
UNIQUE KEY `name` (`name`),
KEY `access` (`access`),
KEY `created` (`created`),
KEY `mail` (`mail`)
);
CREATE TABLE `profile_fields` (
`fid` int(11) NOT NULL auto_increment,
`title` varchar(255) default NULL,
`name` varchar(128) NOT NULL default '',
`explanation` text,
`category` varchar(255) default NULL,
PRIMARY KEY (`fid`),
UNIQUE KEY `name` (`name`),
KEY `category` (`category`)
);
CREATE TABLE `profile_values` (
`fid` int(10) unsigned NOT NULL default '0',
`uid` int(10) unsigned NOT NULL default '0',
`value` text,
PRIMARY KEY (`uid`,`fid`),
KEY `fid` (`fid`)
);
SELECT u.uid, pf.title, pv.value
FROM users AS u, profile_values AS pv, profile_fields AS pf
WHERE pv.id = u.uid, pf.fid = pv.fid
ORDER BY u.uid
Is something like this what your looking for? What do the tables look like in terms of foreign keys? You may want to throw a DISTINCT in right after SELECT.
This is all correct. It is not clear where organization, Website, Country fields should come from (as we don't know your database structure), but, for example, if country was a column of profile_fields, you would simply add SELECT ..., pf.country ... to get the desired data.
It seems like your schema is not accurately maintaining the required information. First off in the User table you have name as 1 attribute, thus splitting first and last name must be done by some other means. Secondly it is not clear where the company name or website information is stored. Please provide a logical mapping from the desired output to the attributes in the database tables.