How to get a summary using only SQL from 3 tables - mysql

I have 3 tables:
Table posts
post_id
category_id
title
Table visits
visit_id
post_id
visit_date
Table categories
category_id
category_name
I need to get something like this (assuming that table visits has 10 rows)
Category 1 (categories.category_name) / visits(count) = 5
Category 2 (categories.category_name) / visits(count) = 1
Category 3 (categories.category_name) / visits(count) = 4
How can I get a similar result using only MySQL?
I tried with INNERs, no success

It's a simple query. You need to join all three tables, and finally group the result by category name. It should look like:
select
c.category_name,
count(*)
from categories c
join posts p on p.categoryid = c.category_id
join visits v on v.post_id = p.post_id
group by c.category_name
order by c.category_name

Related

Complex SQL Query Syntax

I want make a query to mysql database that gets me the products that are available, have sale_id of anything1 or anything2 or both and belong to categories of Ids a or b or both from table category_product which has (category_product table) 2 columns product_id and category_id since my products can belong to multiple categories.
HERE IS MY QUERY:
SELECT *
FROM products
WHERE available = 1
AND sale_id = 3
OR sale_id = 4
AND id IN (
SELECT product_id
FROM category_product
WHERE category_id = 2
OR category_id = 3
)
But It didn't work!!!
The Result was that it got the first query correct the one with available = 1 and sale_id = 3 or 4 or both.. But the products it got didn't belong to categories 2 or 3 or both
Any Help Please!!!
I think you just need parentheses or IN:
SELECT p.*
FROM products p
WHERE p.available = 1 AND
p.sale_id IN (3, 4) AND
p.id IN (SELECT product_id
FROM category_product cp
WHERE category_id IN (2, 3)
);
You seem to be learning SQL -- or at least boolean expressions. AND and OR don't automatically do what you want. When you are mixing them, use parentheses until you get the hang of it.
Your condition parses as:
WHERE (p.available = 1 AND p.sale_id = 3) OR
(p.sale_id = 4 AND
p.id IN (SELECT product_id
FROM category_product cp
WHERE category_id IN (2, 3)
)
)

How to count make an SQL based on 3 tables

I have three tables and Im trying to count the number of likes per user on all his/her post.
USER TABLE
id name
1 John
2 Joe
POSTS TABLE
id user_id post_title
1 1 Some Title
2 1 Another Title
3 2 Yeah Title
LIKES TABLE
id post_id
1 1
2 1
3 1
4 2
5 3
My expected output is
ID LIKES
1 4
2 1
Im kinda stuck with the code below. I don't know how to add and count the likes table.
SELECT *
FROM user
INNER JOIN posts
ON user.id = posts.user_id;
You need to extend the join to the LIKES table and then use GROUP BY to group by the user ID and COUNT() all of the records for that user...
SELECT user.id, COUNT(likes.id)
FROM user
INNER JOIN posts ON user.id = posts.user_id
INNER JOIN likes ON posts.id = likes.post_id
GROUP BY user.id
If you want to list people who don't have posts or likes, then you should use outer joins (so change INNER JOIN to LEFT JOIN) so that these users show up.
For your desired result, you don't need the user table. You can simply do:
SELECT p.user_id, COUNT(*)
FROM posts p JOIN
likes l
ON l.post_id = p.id
GROUP BY p.user_id;
The only information you are taking from users is the id, which is already in posts. This assumes that all the user_id values in posts are valid, but that seems like a very reasonable assumption.

How to get articles which are part of the same group

I want to retrieve variants of the same article which are part of the same group. DBM is MySQL 5.7.
There are 2 tables:
articles
articles_group
Table articles has the fields:
article_id | title
1 first product
2 second prod
3 3rd prod
4 4th example
Table articles_groups:
group_id | article_id
1 1
1 2
1 3
2 4
In this example I would like to retrieve all other articles which are in the same group as article 1. So that would be article 2 and 3.
My best shot, but somehow pretty complex:
SELECT
art.article_id,
model
FROM
articles art
INNER JOIN
articles_group art_g ON art.article_id = art_g.article_id
WHERE art_g.group_id = (
SELECT ag.group_id
FROM articles a
INNER JOIN articles_group ag ON a.article_id = ag.article_id
WHERE a.article_id = 1
)
How can I retrieve all other articles which belong to the same group of given article in an easy way? I can still change the shema if there is a better setup.
Let's say your given article is 1. To get all articles in same group of given article, you can use subquery to get group_id of given article. Then use outer query to get all articles in same group.
SELECT a.article_id, a.title
FROM articles a
JOIN articles_groups g ON a.ref_id = g.ref_id
WHERE g.group_id = (
SELECT g.group_id
FROM articles a
JOIN articles_groups g ON a.ref_id = g.ref_id
WHERE a.article_id = '1'
)

remove some data from many to many result

I have issue with my many to many database .
I have simple blog system
post |
category |
post_has_category
when I used join to select the posts has not in category "3" ,it's filed (3 is example entry )
because in my database store post category like this
post(id):1
category(id):3
post_has_category:
post_id category_id
1 3
1 4
after I select the post don'n in cat 3 , the post 1 is selected but I don't want it , because it's belongs to cat 3 in other row ..
We can use a subquery to identify all post_id in which a category_id of 3 appeared. Then, we can left join the original table to this subquery and retain only those post_id which did not match to any of the offending ones in the subquery.
SELECT p1.*
FROM posts p1
LEFT JOIN
(
SELECT DISTINCT post_id
FROM posts
WHERE category_id = 3
) p2
ON p1.post_id = p2.post_id
WHERE p2.post_id IS NULL
Note that DISTINCT in the subquery should be unnecessary if a given post_id can only be associated with a given category_id once.

How to properly count rows in table2 related to items in table1 with clause non related to table1

I have simple magazine, and have tables with posts, comments, categories, etc. When listing single category, I want to have sum of comments per post in a listing, but that number is just wrong and it is driving me crazy. Note that single post can be in multiple categories.
Here are the simple tables structures
posts
id | title | categoryid | content | published
---------------------------------------------
comments
id | postid | comment
---------------------
category_rel
postid | categoryid
-------------------
categories
id | category
-------------
I use following sql (simplified to this example):
SELECT posts.*, categories.id AS categoryid,
categories.category AS categorytitle,
COUNT(comments.postid) AS CNT
FROM posts
LEFT JOIN comments ON posts.id = comments.postid
INNER JOIN category_rel ON posts.id = category_rel.postid
INNER JOIN categories ON category_rel.categoryid = categories.id
WHERE posts.published=1
GROUP BY posts.id;
This statement is giving me wrong results, sometning like it's cumulating number of categories post is member of and multiplying with actual number of comments. If I remove category part of SQL (which is not good, I need category Id and name) I receive proper values:
SELECT posts.*, COUNT(comments.postid) AS CNT
FROM posts
LEFT JOIN comments ON posts.id = comments.postid
WHERE posts.published=1
GROUP BY posts.id;
To be more specific:
One of posts have 1 comment and it is member of 7 categories. value CNT is going to 7, not 1.
Any idea how to change first SQL to get proper values?
You want to count the comments per post - not per category. So one way of achieving this would be to do the count first (in a subselect as MySQL has no CTE so far) and then join the results into category table:
SELECT countpost.*, categories.id AS categoryid,
categories.category AS categorytitle
FROM
-- subselect post and comment count
(
SELECT posts.*, count(comments.postid) as CNT FROM posts
LEFT JOIN comments ON posts.id = comments.postid
WHERE posts.published = 1
GROUP BY posts.id
) as countpost
-- join category table
INNER JOIN category_rel ON countpost.id = category_rel.postid
INNER JOIN categories ON category_rel.categoryid = categories.id ;
See this fiddle: http://sqlfiddle.com/#!9/f9c6f/1