How do I select and match from multiple tables? - php

This is my table layout:
-- Table structure for table `areas`
CREATE TABLE IF NOT EXISTS `areas` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL,
`country` varchar(20) NOT NULL,
`city` varchar(20) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- Table structure for table `matches`
CREATE TABLE IF NOT EXISTS `matches` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL,
`view_id` bigint(20) unsigned NOT NULL,
`status` enum('h','n') NOT NULL,
`exp_date` date NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- Table structure for table `users`
CREATE TABLE IF NOT EXISTS `users` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`limit_age` varchar(5) NOT NULL DEFAULT '18:30',
`limit_gender` varchar(2) DEFAULT NULL,
`notifications` int(11) NOT NULL DEFAULT '0',
`name` varchar(30) NOT NULL,
`email` varchar(40) NOT NULL,
`image_big` varchar(120) NOT NULL,
`image_small` varchar(120) NOT NULL,
`crop_data` int(11) DEFAULT NULL,
`visible` tinyint(1) NOT NULL DEFAULT '0',
`age` int(11) DEFAULT NULL,
`registered_at` datetime NOT NULL,
`views` bigint(20) unsigned NOT NULL DEFAULT '0',
`hots` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;
I will try to explain this better:
I have a given ID.
I would like to select one entry from users which is not the ID i have given
AND which user_id does not exist in matches
AND has visible = 1
AND where any country + city matches the given users country + city
Is this the correct way to do it (12 is an example of an given ID):
SELECT *
FROM users a
INNER JOIN areas ON areas.user_id = a.id
WHERE a.id NOT IN (SELECT user_id FROM matches)
AND NOT a.id = '12'
AND a.limit_age = '18:30'
AND a.visible = '1'
AND areas.country = 'sverige'
AND areas.city = 'gbg'
Sorry for the confusion :)

Ok, I'll make an attempt at this:
SELECT *
FROM users a
INNER JOIN areas ON areas.user_id = a.id
WHERE a.id NOT IN (SELECT user_id FROM matches)
AND a.visible = '1'
AND a.limit_age = '18:30'
AND a.limit_gender = 'f'
AND areas.country = ?
AND areas.city = ?;
This is SELECTing from "users", and returning a result only if that user also has an entry in the "areas" table. The first item in the WHERE clause ensures that a row will not be returned if the users.id (a.id) is found in the user_id field on the "matches" table. Next, I added checks for visible = 1, limit_age, and limit_gender as specified in his attempt. Finally, I left country and city parameterized so that they can be added as parameters in the php code. If anything that should give you a starting point.

Related

MySQL query - joining two tables producing duplicate results

I'm running the following MySQL query in PHP.
"SELECT *
FROM `challenges`,`verifications`
WHERE (`challenges`.`user_id`='".$this->record['id']."' OR `challenges`.`opponent_id`='".$this->record['id']."')
AND `challenges`.`is_verified`='0'
AND (`challenges`.`status`='in-progress' OR `challenges`.`status`='pending')
AND
(
(`verifications`.`user_id`='".$this->record['id']."' OR `verifications`.`opponent_id`='".$this->record['id']."')
AND (`verifications`.`user_verified`!=NULL AND `verifications`.`opponent_verified`=NULL)
)
LIMIT 100";
This query is returning duplicate records for some reason. If anyone has any insights, I would greatly appreciate it.
Here is the structure for the two tables (challenges and verifications):
Challenges Table:
CREATE TABLE `challenges` (
`id` int(11) NOT NULL auto_increment,
`wager` int(11) NOT NULL,
`type` varchar(255) NOT NULL,
`user_id` int(11) NOT NULL,
`opponent_id` int(11) NOT NULL,
`start_date` date NOT NULL,
`date_created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
`start_time` time NOT NULL,
`is_verified` tinyint(1) NOT NULL default '0',
`status` varchar(255) NOT NULL default 'pending',
`winner_id` int(11) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ;
Verifications Table:
CREATE TABLE `verify` (
`id` int(11) NOT NULL auto_increment,
`user_id` int(11) NOT NULL,
`opponent_id` int(11) NOT NULL,
`challenge_id` int(11) NOT NULL,
`user_verified` int(11) default NULL,
`opponent_verified` int(11) default NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `challenge_id` (`challenge_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=0;
Thanks for your help, and if you need any more info please let me know.
You have to add condition:
challenges.id = verify.challenge_id
to where clause as below
"SELECT *
FROM `challenges`,`verifications`
WHERE `challenges`.`id` = `verify`.`challenge_id`
AND (`challenges`.`user_id`='".$this->record['id']."'
OR `challenges`.`opponent_id`='".$this->record['id']."')
AND `challenges`.`is_verified`='0'
AND (`challenges`.`status`='in-progress' OR `challenges`.`status`='pending')
AND ( (`verifications`.`user_id`='".$this->record['id']."'
OR `verifications`.`opponent_id`='".$this->record['id']."')
AND (`verifications`.`user_verified`!=NULL
AND `verifications`.`opponent_verified`=NULL)
)
LIMIT 100";
or using ANSI-92
"SELECT *
FROM `challenges` as `challenges`
JOIN `verifications` as `verifications` on `challenges`.`id` = `verify`.`challenge_id`
WHERE (`challenges`.`user_id`='".$this->record['id']."' OR `challenges`.`opponent_id`='".$this->record['id']."')
AND `challenges`.`is_verified`='0'
AND (`challenges`.`status`='in-progress' OR `challenges`.`status`='pending')
AND
(
(`verifications`.`user_id`='".$this->record['id']."' OR `verifications`.`opponent_id`='".$this->record['id']."')
AND (`verifications`.`user_verified`!=NULL AND `verifications`.`opponent_verified`=NULL)
)
LIMIT 100";

Select all threads with tag & the rest of the tags?

I am trying to get all the threads with tag name "test" for example, along with all the other tags. If I add a where clause to my INNER JOIN select then it gets the threads with that tag, but it doesn't get the remaining tags for that thread (each tag is a separate row, I use the group concat to combine them). How can I get the remaining tags also?
I have the following SQL
SELECT `threads`.`id`,
`threads`.`title` AS `title`,
`threads`.`created_at` AS `created_at`,
`threads`.`views` AS `views`,
`threads`.`comments` AS `comments`,
`threads`.`user_id` AS `user_id`,
`tags`
FROM `threads`
INNER JOIN
(SELECT threads_id,
GROUP_CONCAT(DISTINCT `thread_tags`.`thread_tags_title`) AS tags
FROM `thread_tags`
WHERE `thread_tags`.`thread_tags_title` = 'test'
GROUP BY threads_id) thread_tags ON `threads`.`id` = `thread_tags`.`threads_id`
WHERE `threads`.`status` = '1'
ORDER BY `threads`.`views` DESC, `threads`.`created_at` DESC LIMIT 25
OFFSET 0
And the following schemes
Tags
CREATE TABLE `tags` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(200) NOT NULL,
`status` int(11) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`description` varchar(255) DEFAULT NULL,
`doctors` int(11) DEFAULT NULL,
`threads` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
Thread Tags (table with thread id and tag id)
CREATE TABLE `thread_tags` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`threads_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL,
`thread_tags_title` varchar(255) NOT NULL DEFAULT '',
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
Threads
CREATE TABLE `threads` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`title` varchar(200) NOT NULL,
`body` text NOT NULL,
`status` int(11) NOT NULL,
`views` int(11) NOT NULL,
`rating` int(11) NOT NULL,
`comments` int(11) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`metadata` text,
PRIMARY KEY (`id`),
KEY `title` (`title`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
Something like
SELECT threads.*, GROUP_CONCAT(tags.title)
FROM threads AS t
LEFT JOIN thread_tags AS tt ON t.id = tt.threads_id
LEFT JOIN tags AS tt ON tt.tag_id = tags.id
WHERE t.id IN (
SELECT tt.threads_id
FROM thread_tags AS tt
JOIN tags ON tt.tag_id = tags.id
AND tags.title = "test"
)
GROUP BY t.id

PHP/MYSQL - Which Join Statement To Use To Simplify My Queries?

I have these 2 queries and i would like to join them into one but i am unsure of how to go about it.
Query 1:
$query = "SELECT * FROM ".$db_tbl_comics." WHERE ".$db_fld_comics_publisher."='".$pub_id."'
AND ".$db_fld_comics_active."='1' GROUP BY ".$db_fld_comics_arc;
Query 2:
$q2 = mysql_query('SELECT '.$db_fld_arcs_title.' FROM '.$db_tbl_arcs.'
WHERE '.$db_fld_arcs_id.'="'.$result[$db_fld_comics_arc].'"');
Comics Table:
CREATE TABLE IF NOT EXISTS `comics` (
`id` varchar(255) NOT NULL,
`arc` int(255) NOT NULL,
`title` varchar(255) NOT NULL,
`issue` decimal(5,1) DEFAULT NULL,
`price` decimal(10,2) NOT NULL,
`plot` longtext NOT NULL,
`publisher` int(255) NOT NULL,
`isbn` varchar(255) NOT NULL,
`published` date NOT NULL,
`cover` varchar(255) NOT NULL DEFAULT './images/nopic.jpg',
`added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`views` int(255) NOT NULL DEFAULT '0',
`active` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `arc` (`arc`,`title`,`issue`,`publisher`)
);
Arcs Table:
CREATE TABLE IF NOT EXISTS `arcs` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`plot` longtext NOT NULL,
`added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `title` (`title`)
);
What I need to do is get the Arcs Title from the arcs table for the respective comic arc.
You need to use INNER JOIN for that since I presume that records are present on both tables.
SELECT a.*, b.title
FROM comics a INNER JOIN arcs b
on a.id = b.id
WHERE a.Title = 'VALUEHERE'
displays all details from comics table and the title of the arc
as simple as (joining 2 queries in one, by selecting only the required field and using IN):
SELECT
'.$db_fld_arcs_title.'
FROM '.$db_tbl_arcs.'
WHERE '.$db_fld_arcs_id.' IN (
SELECT '.$db_fld_comics_arc.'
FROM '.$db_tbl_comics.'
WHERE '.$db_fld_comics_publisher.'='".$pub_id."'
AND '.$db_fld_comics_active.'='1' GROUP BY '.$db_fld_comics_arc.'
)

Select all possible children with parent in mysql

I have a users table.
I have a certifications table.
Each user can have multiple certifications. Certifications has a user_id foreign key.
How may I select a user as well as all of their certifications in one query?
How may I select users that have certifications?
users table:
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL auto_increment,
`username` varchar(24) default NULL,
`displayname` varchar(24) default NULL,
`email` varchar(64) default NULL,
`password` text,
`signup_date` int(11) default NULL,
`signup_ip` varchar(15) default NULL,
`hash` text,
`verified` tinyint(1) default '0',
`last_login` int(11) default NULL,
`logins` int(11) default NULL,
`status` text,
`recovery_hash` text,
`recovery_initiated` int(11) default NULL,
`last_updated` int(11) default NULL,
`signup_method` text,
`signup_question` int(11) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
certifications table:
CREATE TABLE `certifications` (
`id` int(11) unsigned NOT NULL auto_increment,
`user_id` int(11) unsigned NOT NULL,
`number` varchar(128) default NULL,
`board` varchar(128) default NULL,
`company` varchar(128) default NULL,
`website` varchar(128) default NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
CONSTRAINT `certifications_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
Thank you for reading.
How may I select a user as well as all of their certifications in one query?
SELECT *
FROM certifivations C
LEFT JOIN users U
ON C.user_id = U.id
WHERE U.id=USERID
How may I select users that have certifications?
SELECT *
FROM certifivations C
JOIN users U
ON C.user_id = U.id
GROUP BY U.id
Get all the certifications of user with id of 1 by using a join.
SELECT b.id as certification_id
FROM users AS a
LEFT JOIN certifications AS b
ON a.id = b.user_id
WHERE a.id = 1;
Get all the users that have certifications using an inner join. All users without certs will drop out.
SELECT a.id as users_with_certifications
FROM users as a
JOIN certifications AS b
ON a.id = b.user_id;

MySQL JOIN query more tables and return more result in one select

I would question, sorry my bad english :(
I have multiple tables
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(50) COLLATE utf8_slovak_ci NOT NULL,
`password` varchar(200) COLLATE utf8_slovak_ci NOT NULL,
`status` tinyint(1) NOT NULL,
PRIMARY KEY (`id`,`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_slovak_ci;
CREATE TABLE `user_acl` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`id_user` int(11) unsigned NOT NULL,
`group` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_slovak_ci;
CREATE TABLE `user_profil` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(100) COLLATE utf8_slovak_ci NOT NULL,
`fullname` varchar(100) COLLATE utf8_slovak_ci NOT NULL,
`profil` text COLLATE utf8_slovak_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_slovak_ci;
Query:
SELECT user.*, prf.*, acl.*
FROM (SELECT * FROM user LIMIT 1) AS user
LEFT JOIN user_acl AS acl ON (acl.id_user = user.id)
INNER JOIN user_profil AS prf ON (user.id = prf.id)
I have table user, user_acl, user_profil
table user and user_profil are indexed under id what is the common key
Table user_acl have id_usercommon key with table user (id) in the table but user_acl There are more rows for the table user and I need all rows from a table user_acl in one query.
You can get MySQL to combine values from multiple rows into one row with GROUP_CONCAT:
SELECT user.*, prf.*, GROUP_CONCAT(acl.id), GROUP_CONCAT(acl.group)
FROM user
LEFT JOIN user_acl AS acl ON (acl.id_user = user.id)
INNER JOIN user_profil AS prf ON (user.id = prf.id)
GROUP BY user.id;
You can't. You have to separate query, if you need more than one acl row to one user row.
[EDIT]: But if you need to to it with one query then you should use somekindof bitwise operations. http://codingrecipes.com/how-to-write-a-permission-system-using-bits-and-bitwise-operations-in-php

Categories