SQL SELECT and GROUP - mysql

Here is my problem:
SELECT *
FROM posts
JOIN tags
ON tags.did = posts.did
JOIN users
ON users.username = posts.username
GROUP by tags.did
Now the result only shows one tag when I have two tags for the did. I want it to show all the tags I have for it kinda like this
a post | tag 1, tag 2
but right now, it's showing it like this
a post | tag 1
And I don't know why it won't show the other tag. I hope this is enough relevant information. (Pardon me, I'm a bit of a SQL beginner right now)

TRY (essential part, not tested )
SELECT p.postid, GROUP_CONCAT(t.tags)
FROM posts p
INNER JOIN tags t ON t.did = p.did
INNER JOIN users u ON u.username = p.username
GROUP by t.did

Pseudocode
SELECT post.Text, Coalesce('',select tag +',' from tags where tags.did=posts.did)
FROM posts
or us Group_concat
group concat
SELECT GROUP_CONCAT(Language) As Languages FROM CountryLanguage WHERE CountryCode = 'THA'
I dont have a mysql to test against but you need something like this.My Sql Coalsce

Related

Mysql query that handles both a tagging system and favorites

I'm not really a developer but I'm developing an app as a side project and have become stumped with an SQL query I'm attempting to tackle. This app has collections of images that are tagged. My table structure looks something like this:
images
------
image
path
tag_map
------
image
tag
tags
-------
tag
tag_name
favorites
-------
user
image
My query is working well for the tagging system, however, I am not succeeding in adding a query for the favorites. Currently my query looks like this:
SELECT i.*, IF (c.image IS NOT NULL,1,0) as favorited
FROM (images i, tag_map m, tags t)
LEFT JOIN favorites as c ON c.image = i.image
WHERE m.tag = t.tag
AND (t.tag_name IN ('umbrella'))
AND i.image = m.image
AND c.image = i.image
GROUP BY i.image
HAVING COUNT( i.image ) = 1
While this query works, it excludes rows that do note have an entry in the favorites table. The following simplified (sans tag system) query works:
SELECT i.*, c.*,
IF(c.image IS NOT NULL,1,0) as fave
FROM (images as i)
LEFT JOIN collection as c ON c.image = i.image
Any suggestions or points in the right direction would be awesome! Thanks!
As it would turn out, my query works fine once I removed the superfluous "AND c.image = i.image" I had inadvertently left in there.
The working query is:
SELECT i.*, IF (c.image IS NOT NULL,1,0) as favorited
FROM (images i, tag_map m, tags t)
LEFT JOIN collections as c ON c.image = i.image
WHERE m.tag = t.tag
AND (t.tag_name IN ('umbrella'))
AND i.image = m.image
GROUP BY i.image
HAVING COUNT( i.image ) = 1

PHP Mysql, cannot get right results

I'm trying to join together two tables, but I cannot get the results I want to get.
So the results I'm looking for is that, I want to be able to "echo" out all the Topic where a user has been involved, by either creating the topic och making a post/comment inside the topic.
I've tried something like:
SELECT *
FROM Topics
LEFT JOIN Posts ON Topics.topic_creator = 'AAAA'
OR Posts.Post_creator = 'AAAA'
But with this sql I don't really get the result, it's giving me multiple sample of same Topic_id and sometimes it just prints out all topics/posts.
So the tables I'm working with is:
Table 1 - Topics:
Table 2 - Posts
I would be grateful if someone more experienced would like to help me solve this PHP problem.
Thanks in advance
Try something like that :
SELECT DISTINCT *
FROM Topics
LEFT JOIN Posts ON Topics.Page_id = Posts.Page_id
where Topics.topic_creator = 'AAAA' OR Posts.Post_creator = 'AAAA'
You can join both tables with the column page_id so you could do something like this:
SELECT *
FROM Topics
INNER JOIN Posts ON Topics.Page_id = Posts.Page_id
WHERE Posts.Post_creator = 'the_name';
It's just an example, I hope it can help you.
Your question is basically not a php problem but rather an sql problem. Your SQL Join should look something like this
SELECT *
FROM Topics
LEFT JOIN Posts ON Topics.id = Posts.Topic_id
WHERE Topics.Topic_creator = 'AAA'
The best way to do this is with a UNION. One query returns all the topics that the user created, the other returns all the topics that the user posted in.
SELECT *
FROM Topics
WHERE Creator = 'AAA'
UNION
SELECT DISTINCT t.*
FROM Topics AS t
JOIN Posts AS p ON p.Topic_id = t.id
WHERE t.Creator != 'AAA'
AND p.Post_creator = 'AAA'
Also, notice that the second query only selects t.*, since you just want topic information, not information about all his posts. And DISTINCT prevents it from returning a row for each of his posts in the topic.
This will do what you want:
select * from Topics t
join Posts p
on t.id = p.Topic_id
where t.Topic_creator = 'AAA'
or p.Post_creator = 'AAA'
Make sure you have indexes on t.id, p.Topic_id, t.Topic_creator and p.Post_creator
try this
SELECT * FROM Topics t LEFT JOIN Posts p ON t.topic_creator = p.Post_creator

MySQL foreign key multi join

I have this table setup (simplified):
ads
- id
- brand_id
brands
- id
tags
- taggable_type
- taggable_id
- tag
The taggable_type in the tags table will be either "Ad" or "Brand", the taggable_id will identify the ad_id or brand_id respectively, and then the tag is a string.
Ads inherit their brand's tags, and I'm trying to write a search query that pulls up a set of ads for a given set of tags, where those tags belong to either the ad itself or the brand associated with that ad.
These tables can all be fairly large, so I need it to be efficient.
Here's what I have (this isn't working)
SELECT
a.*
FROM
ads a
JOIN
((
SELECT
*
FROM
tags
WHERE
tag IN ({$tags})
AND taggable_type = "Ad"
) t FULL JOIN (
SELECT
*
FROM
tags
WHERE
tag IN ({$tags})
AND taggable_type = "Brand"
)) tt
ON (t.taggable_id = a.id) OR (tt.taggable_id = a.brand_id);
For starters, I'm getting an error on the full join. I've also tried an inner join and a left join, and it's still not working. I feel like I'm just doing something fundamentally stupid. Any help?
Like this it should work
SELECT DISTINCT
ads.*
FROM
ads
LEFT JOIN brands
ON ads.brand_id = brands.id
INNER JOIN tags
ON (
tags.taggable_type = 'brand'
AND brands.id = tags.taggable_id)
OR (
tags.taggable_type = 'ad'
and ads.id = tags.taggable_id)
WHERE
tags.tag IN ('tag 1', 'tag 2', 'tag 7')
SQL Fiddle
But you might also want to think about your database structure again.
Perhaps a setup like the following would suit you better.
ads(id, brand_id)
brands(id)
tags(id)
tags_ads(tag_id, ad_id)
tags_brands(tag_id, brand_id)
Would have the benefit of being able to assign a tag to more than one brand or ad. Or to a brand and an ad...

Count(*) won't display when result is 0 when using group by

Sorry I couldn't think of a better title...
So I have this database where I have a table 'bibitems' (basicly texts) 'tags' (the tags the text is filed under) and 'taglinks' (Associative entity between a bibitem and a tag)
So on my page I want to display every tag, directly followed by the amount of documents that are filed under that tag
so if 2 documents are under 'java' it's say
java (2)
SELECT
tags.id,
naamnl,
COUNT(*) AS 'count'
FROM
tags,
bibitems,
taglinks
WHERE
bibitems.id=taglinks.item_id
AND tag_id=tags.id
GROUP BY
naamnl
This works well when there are documents filed under a certain tag.
But when there's a tag that's unused so far, it won't pop up.
I want it to display java (0) in that case
SELECT tags.id,
tags.naamnl,
COUNT(bibitems.id) AS 'count'
FROM tags
LEFT
OUTER
JOIN taglinks
ON taglinks.tag_id = tags.id
LEFT
OUTER
JOIN bibitems
ON bibitems.id = taglinks.item_id
GROUP
BY tags.id,
tags.naamnl
;
or
SELECT tags.id,
tags.naamnl,
( SELECT COUNT(*)
FROM bibitems
WHERE bibitems.id IN
( SELECT taglinks.item_id
FROM taglinks
WHERE taglinks.tag_id = tags.id
)
)
FROM tags
GROUP
BY tags.id,
tags.naamnl
;
(Take your pick.)
Read on the difference between INNER and OUTER joins.
SELECT tag.id, naamnl, COUNT(taglink.tag_id) AS 'count'
FROM tag
LEFT OUTER JOIN taglink ON taglink.tag_id=tag.id
LEFT OUTER JOIN bibitem ON bibitem.id=taglink.item_id
GROUP BY tag.id, naamnl
Something like thisshould do it. (It is difficult since you did not provide the full table schemas.)
SELECT
i.naamnl,
COALESCE(t.Count, 0) AS Count
FROM
bibitems i
LEFT JOIN
(
SELECT
tag_id,
COUNT(*) AS Count
FROM
taglinks
GROUP BY
item_id
) t
ON
t.tag_id = i.tag_id

Mysql Tag Query - Repeated values

I'm working on a tag-based search. The user can search one tag or multiple tags. I've got 3 tables: Content, Content_Tags and Tags. Content_Tags does the link between content and tags. The query has to return all the information of the content retrieved, this includes a concatenated string of all tags from that content.
Using an example from other question I've managed to reach this query:
SELECT content.Name,GROUP_CONCAT(t2.Tag SEPARATOR ' ') FROM content
JOIN content_tags ct1 ON content.ContentID = ct1.ContentID
JOIN tags t1 on ct1.TagID = t1.TagID AND t1.Tag IN('grass','texture')
JOIN content_tags ct2 ON ct2.ContentID = content.ContentID JOIN tags t2 ON ct2.TagID = t2.TagID GROUP BY content.ContentID;
The query works fine when searching for 1 tag, but using IN('grass','texture') the GROUP_CONCAT will return 'grass grass texture texture' (repeating the tags).
I don't know MySQL this deep, how could I fix this problem?
SELECT content.name,
(
SELECT GROUP_CONCAT(cta.tag)
FROM content_tags cta
WHERE cta.contentID = ct.contentID
)
FROM content_tags ct
JOIN content c
ON c.contentId = ct.contentId
WHERE ct.tag IN ('grass', 'texture')
GROUP BY
ct.contentId
HAVING COUNT(*) = 2