MySQL Query returning same row twice - mysql

I am trying to display data using 3 tables
posts
- id
- category_id
- user_authors_id
- title
- status
user_authors
- id
- author_name
categories
- id
- name
subcategories
- id
- name
What I am trying to do is. I am creating a view panel that will display the posts. So, i am using 3 tables. From user_authors I'll get the author name, from categories table I'll get the category name, now the category tables have subcategory id, so I also want to get the subcategory name.
I am having two rows in the posts table with id 29 and 30 but when i run the below query it shows 2 entries with the same data.
SELECT
posts.id,
categories.name AS cat_name,
subcategories.name AS subcat_name,
posts.title,
user_authors.author_name,
posts.created,
posts.status
FROM posts
INNER JOIN user_authors ON (user_authors.id = posts.user_author_id)
INNER JOIN categories ON(posts.category_id = categories.id)
INNER JOIN subcategories ON (categories.id = subcategories.category_id)
But, if I remove this statement INNER JOIN subcategories ON (categories.id = subcategories.category_id) and run the query, it runs perfect, all the rows are shows properly.
What's happening, I am not trying to get it. Where is the query wrong, also it's showing no error.

INNER JOIN subcategories ON (categories.id = subcategories.category_id)
As it is, for your query to return what you expect, there must be one and only one record in subcategories matches the given post :
if more than one subcategory matches a given post, the post line will be duplicated in the results
if no subcategory matches a given post, the post will not appear in the results
Depending on your use case, you want :
not to JOIN subcategory, to avoid duplicating posts
LEFT JOIN subcategory instead of INNER JOIN subcategory to avoid posts without subcategory to be filtered out
If you do have multiple subcategories for a given post and you still want to display a single row in the results, you can use the GROUP_CONCAT aggregate funtion to concatenate the subcategories into one field :
SELECT
posts.id,
categories.name AS cat_name,
GROUP_CONCAT( subcategories.name, ', ') AS subcat_names,
posts.title,
user_authors.author_name,
posts.created,
posts.status
FROM posts
INNER JOIN user_authors ON (user_authors.id = posts.user_author_id)
INNER JOIN categories ON(posts.category_id = categories.id)
LEFT JOIN subcategories ON (categories.id = subcategories.category_id)
GROUP BY
posts.id,
categories.name,
posts.title,
user_authors.author_name,
posts.created,
posts.status

Related

How to get result from using subquery

I am using MySQL to get some additional information from database. I am trying to do widget bar:
Here is table structure:
My query:
SELECT * FROM `product` WHERE category in (SELECT name FROM category where id='5')
What i want is i need to display category names and products numbers.
But above query gives me empty result set. What am i doing wrong ?
Its only my assumption, since there is little info
This query gets a list of categories and for each adds a count of products having id of that category
select c.id, c.name, count(p.id) count
from category c
left join
product p
on p.category = c.id
group by c.id
You will get rows with category id, category name, product count

How to compare data in two tables and display data from one table

I have 2 tables with the following structure:
categories
id
status
name
created
posts
id
status
category_id
title
excerpt
featured_image
created
user_authors
id
status
author_name
created
I am using the following query:
$query = "SELECT posts.id, posts.category_id, user_authors.author_name, posts.user_author_id, posts.title, posts.post_slug, posts.featured_image, posts.excerpt, posts.created FROM posts, user_authors INNER JOIN categories ON(posts.category_id = categories.id) WHERE posts.status = 1 AND categories.name LIKE = %".$_GET['category']."%";
What i am trying to do is, i am having an url www.xyz.com/technology
where technology is a parameter(category) according to that i will select the posts to display.
I am showing the data where posts.category_id = categories.id AND category_name = $_GET['category']
I am not able to extract any data, I am confused that whether my query is wrong or my logic is wrong?
Can anyone help me solving this logic?
You can not use = with LIKE clause and you did not write any relation between posts and user_authors tables.
The correct query should be:
$query = "SELECT posts.id, posts.category_id, user_authors.author_name, posts.user_author_id, posts.title, posts.post_slug, posts.featured_image, posts.excerpt, posts.created FROM posts INNER JOIN user_authors ON (user_authors.id = posts.user_author_id) INNER JOIN categories ON (posts.category_id = categories.id) WHERE posts.status = 1 AND categories.name LIKE '%".$_GET['category']."%'";
If you are finding only for one categories.name you can remove % from query, this will help mysql to search records if categories.name column has index.
Consider removing the user_author from the select, as there is no join to link the three tables in your command.
Your query has a = with LIKE which is not correct in mysql. The correct way should be,
categories.name LIKE '%". $_GET['category']."%'"
Note the removal of = and enclosing with '
Edit:
According to your reply the new query should look like below.
SELECT posts.id, posts.category_id, user_authors.author_name, posts.user_author_id, posts.title, posts.post_slug, posts.featured_image, posts.excerpt, posts.created
FROM posts INNER JOIN categories ON posts.category_id = categories.id
INNER JOIN user_authors ON posts.id = user_authors.id
WHERE posts.status = 1 AND categories.name LIKE '%".$_GET['category']."%'"

Multi joined MySQL query has an issue

I have the following query, the job scenario is:
I have three tables. Categories, Roles and Roles_to_categories table.
roles_to_categories table:
--id-- --role_id-- --category_id--
A role in roles table, may be bound to several categories in a pivot table named roles_to_categories. I want a role, for instance admin to fetch all the categories from the table categories which are bound to it in table roles_to_categories.
It works fine, but the problem is when aggregation comes in: GROUP_CONCAT().
I want to just get the list of parent categories, and include their children in a separate column by using GROUP_CONCAT(). My problem is that GROUP_CONCAT() seems to ignore the roles_to_categories pivot table when it retrieves the list of children, which means it includes the children of the a certain category that is NOT ALLOWED (I mean there is no record in roles_to_categories to bind it a role)
The query is:
select categories.name as cat_name, categories.id as cat_id,
roles.name as role_name, roles.id as role_id, roles_to_categories.id as cat_id, roles_to_categories.role_id as role_id,
roles_to_categories.category_id,
group_concat('name: ', categories2.name) as cat_children
FROM roles left join roles_to_categories on roles.id = roles_to_categories.role_id
left join categories on roles_to_categories.category_id = categories.id
left join categories as categories2 on categories2.parent_id = categories.id
WHERE roles.name = "admin";
It selects required columns from all three tables, starting from roles then it left joins to roles_to_categories to get its related records and then re-left-joins on categories table from roles_to_categories to select categories whose ids exists in the fetched records and ....
group_concat is an aggregate - you'll need to group by all non-aggregated columns in your select list.
You've also included multiple aliases of both sides of joined columns in your query - this will be confusing and redundant, and aliased category.id and roles_to_category.id to cat_id.
In this case, since you want to concatenate all children of a parent category, this will be like so:
select
categories.name as cat_name, categories.id as cat_id,
roles.name as role_name, roles.id as role_id,
roles_to_categories.id as roles_to_cat_id,
group_concat('name: ', categories2.name) as cat_children
FROM
roles left join roles_to_categories
on roles.id = roles_to_categories.role_id
left join categories on roles_to_categories.category_id = categories.id
left join categories as categories2 on categories2.parent_id = categories.id
WHERE
roles.name = 'admin'
GROUP BY
categories.name, categories.id, roles.name, roles.id, roles_to_categories.id;

how to combine these two queries into one

I have three tables: posts, cat_collection, and cat_mapping
posts contains the fields you would expect to see in a table named posts
id, type, title, body, author, email, date, ect..
cat_collection contains id, name, description
cat_mapping contains *id, collection_id, post_id*
I currently have two queries, the first one selects the information from posts, the second retrieves the associated categories from cat_collection and cat_mapping
first
SELECT post.id, post.type, post.title, post.body, post.date, post.author, post.email
FROM posts AS post
WHERE post.id = 1
second
SELECT cat.name
FROM cat_collection AS cat
LEFT JOIN cat_mapping AS map ON map.collection_id = cat.id
WHERE map.post_id = 1
Is there a way to return all of the post information, as well as the list of associated categories with a single query?
If I understand your data model, you just need another left join. You may want to re-order the joins to make sure that your query is efficient and returns the right data.
SELECT
posts.id,
posts.type,
posts.title,
posts.body,
posts.date,
posts.author,
posts.email,
cat.name
FROM
posts
LEFT JOIN
cat_mapping AS map ON map.post_id = posts.id
LEFT JOIN
cat_collection AS collection ON map.collection_id = collection.id
WHERE
posts.id = 1
Please think carefully about your aliases. Aliasing "posts" to "post" is silly. Aliasing "cat_collection" to cat is confusing - the table is about collections of cats, not cats.

How can I join these two queries?

Here's what I want to accomplish:
Select all rows from table "posts" while also fetching linked entities, such as the author (from table "users") and the names of the categories the post belongs to (from table "categories").
These are my two queries so far:
This one fetches the posts:
SELECT
posts.*
, users.authorName AS author
FROM posts
INNER JOIN users
ON users.id = posts.author
And this one fetches a comma separated list of categories for a specific post:
SELECT
GROUP_CONCAT(categories.category) AS categories
FROM categories
INNER JOIN post_category
ON post_category.categoryID = categories.id
WHERE
post_category.postID = ?
The two queries on their own work fine.
Naturally when the two are combined, I wouldn't need the WHERE clause of the second query.
I tried using the second query as a sub-query within the first one's SELECT clause, but that fetched a comma separated list of ALL categories for ALL posts. I want only the categories for the post I'm currently iterating over.
Any help would be greatly appreciated, and I apologize if any of this is unclear - it's hard enough for me to think about, let alone describe to other people ;)
Something like this:
SELECT posts.*, users.authorName AS author,
GROUP_CONCAT(categories.category) AS categories
FROM posts, users, categories, post_category
WHERE users.id = posts.author
AND post_category.categoryID = categories.id
AND post_category.postID = posts.id
GROUP BY posts.* /* list actual columns here */, author
Or did I miss something?
I think your subquery approach should work fine, but you still need the where clause in your subquery. How else would MySQL know which rows to retrieve? Try:
SELECT posts.*, users.authorName AS author,
(SELECT GROUP_CONCAT(categories.category)
FROM categories
INNER JOIN post_category ON post_category.categoryID = categories.id
WHERE post_category.postID = posts.postID) AS categories
FROM posts
INNER JOIN users ON users.id = posts.author