Convert MySQL subquery to JOIN query - mysql

I'm trying to get the quotes.quote, authors.author and tags.tag from the following table structure,
CREATE TABLE IF NOT EXISTS `authors` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`author` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `quotes` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`quote` text COLLATE utf8_unicode_ci NOT NULL,
`author_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `quotes_author_id_foreign` (`author_id`),
);
CREATE TABLE IF NOT EXISTS `quote_tags` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`tag_id` int(10) unsigned NOT NULL,
`quote_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `tags` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`tag` varchar(225) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
);
ALTER TABLE `quotes`
ADD CONSTRAINT `quotes_author_id_foreign` FOREIGN KEY (`author_id`) REFERENCES `authors` (`id`);
But here the problem is, there can be multiple entry in the tags table for each quotes and I want to retrieve it in the comma separated format.
Here is what I have tried so far,
SELECT `quotes`.`id` , `quotes`.`quote` , `authors`.`author` , (
SELECT GROUP_CONCAT( `tag` )
FROM tags
JOIN quote_tags
WHERE quote_tags.tag_id = tags.id
AND quote_tags.quote_id = quotes.id
) as tags
FROM `quotes`
INNER JOIN `authors` ON `authors`.`id` = `quotes`.`author_id`
INNER JOIN `topics`
But I don't want to use sub queries to get that done.
Please help me in building this query without using sub queries.

SELECT `_quotes`.`id` , `_quotes`.`quote` , `_authors`.`author`
,GROUP_CONCAT( `tag` )
FROM `_quotes`
INNER JOIN `_authors` ON `_authors`.`id` = `_quotes`.`author_id`
inner join _tags
JOIN _quote_tags
on _quote_tags.tag_id = _tags.id
AND _quote_tags.quote_id = _quotes.id
INNER JOIN `_topics` group by `_quotes`.`id`,`_tags`.`id`

Related

Joining two tables with a LIKE statement

I am trying to join my tables with a LIKE STATEMENT and my current query is this :
SELECT
COUNT(comment_id) AS nb,
produit.nom
FROM
comments
INNER JOIN produit ON comments.comment_location like (select '%'+produit.id+'%')
GROUP BY
comment_location
and the SQL FOR THE TABLES is this :
table comments:
CREATE TABLE `comments` (
`comment_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`comment_date` datetime NOT NULL,
`comment_content` varchar(255) NOT NULL,
`comment_location` varchar(255) NOT NULL,
PRIMARY KEY (`comment_id`),
KEY `user_id` (`user_id`),
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8
table produit :
CREATE TABLE `produit` (
`id` int(11) NOT NULL,
`nom` varchar(25) NOT NULL,
`description` varchar(200) NOT NULL,
`categorie` varchar(25) NOT NULL,
`image` varchar(200) NOT NULL,
`prix` float NOT NULL,
`quantite` int(11) NOT NULL,
`prix_initiale` float NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_CATEGORIE` (`categorie`),
CONSTRAINT `FK_CATEGORIE` FOREIGN KEY (`categorie`) REFERENCES `categorie` (`nom`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
my query does execute but doesn't return the table i was looking for
but if i try replacing produit.id in (select '%'+produit.id+'%') with a constant the table shows the corresponding rows .
What am i doing wrong
You need to modify query as below. You dont need SELECT again in the LIKE clause.
SELECT
COUNT(comment_id) AS nb,
produit.nom
FROM
comments
INNER JOIN produit ON comments.comment_location like CONCAT('%',produit.id,'%')
GROUP BY
comment_location
SELECT COUNT(comment_id) AS nb, produit.nom AS nom FROM comments INNER JOIN produit ON comments.comment_location LIKE CONCAT('%', produit.id, '%')
GROUP BY comment_location
by #Phil

MySQL gather data JOIN

I currently have these two tables
CREATE TABLE IF NOT EXISTS `players` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`group_id` int(11) NOT NULL DEFAULT '1',
`account_id` int(11) NOT NULL DEFAULT '0',
`level` int(11) NOT NULL DEFAULT '1',
`vocation` int(11) NOT NULL DEFAULT '0',
...
) ENGINE=InnoDB;
And
CREATE TABLE IF NOT EXISTS `player_storage` (
`player_id` int(11) NOT NULL DEFAULT '0',
`key` int(10) unsigned NOT NULL DEFAULT '0',
`value` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`player_id`,`key`),
FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
I want to execute the following query
SELECT
a.value,
b.name,
b.level,
b.vocation
FROM
player_storage a,
players b
LEFT JOIN players_online c AS t
ON c.player_id = b.id
WHERE
a.player_id = b.id
AND a.key = 6723
ORDER BY a.value DESC LIMIT 20
Thing is I also want to see if the record exists on the table players_online
CREATE TABLE IF NOT EXISTS `players_online` (
`player_id` int(11) NOT NULL,
PRIMARY KEY (`player_id`)
) ENGINE=MEMORY;
However my query seems to work but its not getting if the player_id exists on players_online
I only get the fields value, name, level, vocation but not a single field related to players_online
You should add a field related to your "online" table.
For example:
SELECT ...,
IF(c.player_id IS NULL, 'offline', 'online') online
FROM ...
And sure, you must to fix issue with double alias in players_online c As t
SQLFiddle

how can i extract total forum_question and fourm_answer count as subject wise in mysql i have below mysql structure

forum_question :
CREATE TABLE IF NOT EXISTS `forum_question` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`question` text NOT NULL,
`subject_id` int(11) NOT NULL,
`student_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `subject_id` (`subject_id`,`student_id`),
KEY `student_id` (`student_id`)
)
forum_answer table
CREATE TABLE IF NOT EXISTS `forum_answer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`answer` text NOT NULL,
`question_id` int(11) NOT NULL,
`faculty_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `question_id` (`question_id`,`faculty_id`),
KEY `faculty_id` (`faculty_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
and subject table
CREATE TABLE IF NOT EXISTS `subject` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(150) NOT NULL
)
Try this edited query, I am sure this will work
SELECT
COUNT(que.id) AS totalQuestions,
(SELECT COUNT(DISTINCT(forum_answer.id))
FROM
forum_answer
WHERE
forum_answer.question_id = que.id
GROUP BY que.id)
AS totalAns
FROM
forum_question que
INNER JOIN
subject sub
ON (que.subject_id = sub.id)
WHERE
que.id > 0
GROUP BY sub.id
If by total you mean the total amount of rows, you can do the following:
`SELECT COUNT(*) FROM forum_question WHERE subject_id=YOURSUBJECT`
if you want just all rows, remove the WHERE clause.
Please you can try this Query
SELECT
subject.name AS subject_name,
count(forum_question.id) AS total_question,
(SELECT count(forum_answer.id)
FROM
forum_answer
WHERE
forum_answer.question_id = forum_question.id) AS total_answer
FROM
subject
Inner Join forum_question ON subject.id = forum_question.subject_id
GROUP BY subject.id
Sorry it was my mistake. now I edited the query and hope it will work for you

Internationalization of sql query

I have the following SQL tables:
-- Create syntax for TABLE 'companies'
CREATE TABLE `companies` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`country` varchar(255) NOT NULL DEFAULT '',
`city` varchar(255) NOT NULL DEFAULT '',
`address` text NOT NULL,
`logo` varchar(255) NOT NULL DEFAULT 'empty',
`size` int(11) NOT NULL DEFAULT '32',
PRIMARY KEY (`id`),
KEY `city` (`city`),
KEY `country` (`country`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
-- Create syntax for TABLE 'i18n'
CREATE TABLE `i18n` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`lang` varchar(2) DEFAULT NULL,
`word` text,
`english` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- Create syntax for TABLE 'tags'
CREATE TABLE `tags` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
-- Create syntax for TABLE 'tagsForCompany'
CREATE TABLE `tagsForCompany` (
`company` int(11) DEFAULT NULL,
`tid` int(11) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I have the following sql query (thanks to #Rockse):
SELECT c.*
FROM
(SELECT *
FROM companies
WHERE city = "<Some City>" AND country = "<Some Country>") AS c
INNER JOIN tagsForCompany AS tc ON c.id = tc.Company
INNER JOIN tags AS t ON t.id = tc.TID
WHERE t.Name REGEXP '<a keyword>'
I need to be able to search for Companies with a keyword written in another language by searching in the i18n table for a translation. So that searching for restaurant will give the same results as searching for レストラン (restaurant in Japanese) or ristorante (restaurant in italian).
Honestly I have no idea what to edit in the query, my SQL knowledge is a bit limited.
The solution was easier than I thought:
If someone would improve, I would be more than happy
SELECT c.*
FROM i18n, (SELECT *
FROM companies
WHERE city = "<some city>" AND country = "<some country>") AS c
INNER JOIN tagsForCompany AS tc ON c.id = tc.Company
INNER JOIN tags AS t ON t.id = tc.TID
WHERE t.Name = i18n.`english` AND i18n.word REGEXP "<some word>" OR t.Name REGEXP "<the same word as before>"
But for doing that I had to change all the tables to utf-8

Get same IDs from Detail Table

I have 2 tables in my mysql database:
CREATE TABLE IF NOT EXISTS `RECIPES` (
`recipes_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(50) COLLATE utf8_bin NOT NULL,
`text` varchar(2000) COLLATE utf8_bin NOT NULL,
`count_persons` int(11) NOT NULL,
`duration` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`date` datetime NOT NULL,
`accepted` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`recipes_id`),
KEY `recipes_user_fk` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=88 ;
CREATE TABLE IF NOT EXISTS `RECIPES_POS` (
`recipes_pos_id` int(11) NOT NULL AUTO_INCREMENT,
`recipes_id` int(11) NOT NULL,
`ingredients_id` int(11) NOT NULL,
`ingredients_value` int(11) NOT NULL,
PRIMARY KEY (`recipes_pos_id`),
KEY `recipe_pos_rec_id` (`recipes_id`),
KEY `recipes_pos_ingredient_fk` (`ingredients_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=58 ;
In the Recipe_Pos Table are many entries. This table shows what ingredients are used in the Recipe.
Now i want to find the recipe which contains incredients like powder and sugar:
SELECT r.recipes_id FROM RECIPES r, RECIPES_POS rp WHERE r.recipes_id = rp.recipes_id AND rp.ingredients_id =6 AND rp.ingredients_id =4
this statment is wrong because a entry in Recipe_Pos can'T contains both incredients.
Whats the right query? It should works with only 1 incredient and more
select r.recipes_id
from RECIPES r
inner join RECIPES_POS rp on r.recipes_id = rp.recipes_id
where rp.ingredients_id in (4, 6)
group by r.recipes_id
having count(distinct rp.ingredients_id) = 2