I have 4 tables:
users (id, name, email);
id | name | email
1 | ABC | abc#gmail.com
2 | XYZ | xyz#gmail.com
3 | AAA | aaa#yahoo.com
papers(id, title, content, created_by)
id | title | content | created_by
1 | This is title 1 | This is content 1 | 1
2 | This is title 2 | This is content 2 | 1
3 | This is title 3 | This is content 3 | 3
4 | This is title 4 | This is content 4 | 1
5 | This is title 5 | This is content 5 | 3
6 | This is title 6 | This is content 6 | 2
rating(id, paperId, star)
id | paperId | star
1 | 1 | 2
2 | 2 | 4
3 | 3 | 4
4 | 2 | 2
5 | 1 | 3
comments(id, paperId, msg)
id | paperId | msg
1 | 1 | abcd
2 | 2 | xxxx
3 | 2 | yyyy
4 | 3 | zzzz
5 | 1 | tttt
6 | 4 | kkkk
I want to get fields: papers.id, papers.title, papers.content, users.name,
AVG(rating.star), COUNT(comments.msg)
And I execute a query like:
SELECT papers.id, papers.title, papers.content, users.name,
AVG(rating.star) AS avg_star , COUNT(comments.msg) AS num_of_cmt
FROM papers
JOIN users ON users.id = papers.created_by
LEFT JOIN rating ON rating.paperId = papers.id
LEFT JOIN comments ON comments.paperId = papers.id
WHERE papers.id = 1
Then result is false at "num_of_cmt" field:
id title content name avg_star num_of_cmt
1 This is title 1 This is content 1 ABC 2.5000 4
Above, 'num_of_cmt' is 4 instead of 2. Why?
Both ratings and comments have multiple rows for paperid = 1. So, joining the tables yields four results, with the following ids:
ratings comments
1 1
1 5
5 1
5 5
Hence, the count is 4. You can fix the count by doing count(distinct comments.id). However, the average is going to be off.
One way to fix this problem is by aggregating ratings and comments in subqueries.
Related
I am trying to group a record only if two of the fields repeat themselves.
I am designing a social sharing photo app. users can share, like and comment on thers photo. Each action (share, comment, like) will appear on their friends wall.
The Problem is that when a user do all the three actions, the picture appears three times instead of one with the three action on it.
Data in database is like this (activities_tb)
id | photoID | uiID | action | date
-------------------------------------------
1 | 1 | 2 | like | 01/01/2015
2 | 1 | 2 | share | 02/01/2015
3 | 1 | 4 | share | 03/01/2015
4 | 1 | 2 | comment | 04/01/2015
5 | 2 | 4 | like | 04/01/2015
6 | 2 | 2 | like | 05/01/2015
7 | 2 | 3 | share | 05/01/2015
8 | 2 | 4 | comment | 06/01/2015
8 | 3 | 3 | like | 07/01/2015
9 | 3 | 5 | like | 08/01/2015
10 | 3 | 5 | comment | 08/01/2015
The query result I want to get
id | photoID | uiID | action | date
-------------------------------------------
3 | 1 | 4 | share | 03/01/2015
4 | 1 | 2 | comment | 04/01/2015
6 | 2 | 2 | like | 05/01/2015
7 | 2 | 3 | share | 05/01/2015
8 | 2 | 4 | comment | 06/01/2015
8 | 3 | 3 | like | 07/01/2015
10 | 3 | 5 | comment | 08/01/2015
This is my statement
SELECT id, photoID, uiID, action, date
FROM activities_tb
GROUP BY photoID, uiID.
This combines all the photos by their id returning only three results
I will be glad if anyone can be of help, thank you
You can first select required ids and join on your table:
select tb.*
from activities_tb tb
join(select max(id) as id
from activities_tb
group by photoID, uiID) t on t.id = tb.id
You are looking for "SELECT DISTINCT"
SELECT DISTINCT photoID, uiID, action, date
FROM activities_tb
GROUP BY photoID, uiID.
I've made a table to parent-child relationship (Sections/Subsections or Categories.Subcategories). I want to sort it first by parent 'SectionSort' field then by children 'SectionSort' field.
Example table:
IDSection | SectionParentID | SectionSort | SectionName
-------------------------------------------------------
2 | 0 | 2 | Chapter 2
1 | 0 | 1 | Chapter 1
5 | 1 | 1 | Subchapter 1
4 | 1 | 3 | Subchapter 3
3 | 1 | 2 | Subchapter 2
7 | 2 | 2 | Sunchapter 5
6 | 2 | 1 | Subchapter 4
'SectionSort' filed can be dynamicaly change by moving up and down to column according user needs.
I need to get following result:
IDSection | SectionParentID | SectionSort | SectionName
-------------------------------------------------------
1 | 0 | 1 | Chapter 1
2 | 0 | 2 | Chapter 2
3 | 1 | 1 | Subchapter 1
4 | 1 | 2 | Subchapter 2
5 | 1 | 3 | Subchapter 3
6 | 2 | 1 | Sunchapter 4
7 | 2 | 2 | Subchapter 5
Or something like this:
Chapter 1
-Subchapter 1
-Subchapter 2
-.....
-SubChapter 3
Chapter 2
-Subchapter 4
-Subchapter 5
This is what I try but work only to next level not leve 3 ~ n:
SELECT EvalQuestions.*, Child.SectionSort AS Child_SectionSort, Parent.SectionParentsIDs AS Parent_SectionParentsIDs, Parent.SectionParentNames AS Parent_SectionParentNames,
Parent.SectionName AS Parent_SectionName, Parent.SectionSort AS Parent_SectionSort, Parent.SectionParentID AS Parent_SectionParentID
FROM EvalQuestions INNER JOIN (EvalSections Parent INNER JOIN EvalSections Child ON
Parent.SectionParentID = Child.IDSection) ON
EvalQuestions.SectionID = Parent.IDSection
ORDER BY Parent.SectionSort, Child.SectionSort, QuestionSort
Try this.
select * from Table order by SectionParentID asc,SectionSort asc.
I have this 3 tables:
Users:
user_id|user_nick
1 | a
2 | b
Category:
cat_id|cat_type
1 | a
2 | b
3 | c
4 | d
Meta:
met_id|met_name|met_user|met_type
10 | bla | 1 | 1
11 | blabla | 2 | 2
12 | foo | 1 | 3
13 | blafoo | 2 | 4
14 | foofoo | 1 | 4
15 | foobla | 1 | 4
How can I return something like this ?
user_id|met_type|total
1 | 1 | 1
1 | 2 | 0
1 | 3 | 1
1 | 4 | 2
For just one user and not for all of them.
met_type is a foreign key from Category.
I've tried like this but no success :/
SELECT met_user, met_type, COUNT(*) FROM Meta GROUP BY met_user WHERE met_user = '1'
Query:
SELECT met_user, met_type, count(*)
FROM Meta
WHERE met_user='1'
GROUP BY met_type;
To get empty groups, you can use generateSeries() here:
SELECT m.met_user, g.meta_type, count(m)
FROM generate_series(1, 4) AS g(meta_type)
LEFT OUTER JOIN Meta AS m
ON m.met_user='1'
AND m.met_type=g.meta_type
GROUP BY g.meta_type, m.met_user
ORDER BY g.meta_type;
Check it out! I made an sql fiddle.
I have 5 tables as per below. How is it possible for me to get a list of all training companies that does not have training class data (which means no female or male students), all within a mysql query statement?
select training_companies.*
from training_companies
left join training_centers on training_centers.training_company_id = training_companies.id
left join training_center_programmes on training_centers.id = training_center_programmes.training_center_id
left join training_class_data on training_class_data.training_center_programme_id = training_center_programmes.id
where training_companies.id IS NULL
So far I could only get to here, but I supposed this is wrong. Kindly advise. Thanks.
training_class_data
id | student_category_id | training_centre_programme_id | female | male
1 | 1 | 1 | 10 | 10
2 | 1 | 2 | 10 | 10
3 | 2 | 1 | 10 | 10
4 | 3 | 1 | 10 | 10
training_programmes
id | name
1 | Yoga
2 | Pilates
training_center_programmes
id | training_center_id | status | training_programme_id
1 | 1 | 1 | 1
2 | 2 | 1 | 1
3 | 3 | 1 | 1
4 | 4 | 1 | 2
5 | 5 | 1 | 2
training_centers
id | name | address | postal code | training_company_id
1 | TF Center 1 | abc | 1234 | 1
2 | TF Center 2 | abc | 1234 | 1
3 | TF Center 3 | abc | 1234 | 1
4 | SFT Center 1 | xyz | 2345 | 2
5 | SFT Center 2 | xyz | 2345 | 2
6 | KFT Center 1 | cbd | 4234 | 3
training_companies
id | name | address | postal code
1 | Trim Fitness | abc | 1234
2 | Stay Fit Training | xyz | 2345
3 | Keep Fit Trainers | cbd | 4234
How is it possible for me to get a list of all training companies that
does not have training class data
You just need to use condition d.training_centre_programme_id IS NULL instead of training_companies.id IS NULL:
select DISTINCT c.*
FROM training_companies AS c
LEFT JOIN training_centers AS tc ON tc.training_company_id = c.id
LEFT JOIN training_center_programmes AS p ON p.training_center_id = tc.id
LEFT JOIN training_class_data AS d ON d.training_centre_programme_id = p.id
WHERE d.training_centre_programme_id IS NULL;
SQL Fiddle Demo
I've got two tables in my database. Table 1 is a list of "timelines" and their corresponding owners and title.
Table 2 is a list of users who have access to the timelines but are followers, not owners.
I'm trying to write a query that outputs the lineID's and corresponding titles that are linked to a userID in either of the two tables.
A query for userID 1 would ideally output:
1 a
2 b
3 c
6 f
Hopefully this isn't too confusing but the purpose is to fill a dynamically generated select box with the LineID and Title for a given UserID...
Table 1 ("owners")
--------------------------
| LineID | UserID | Title |
| 1 | 1 | a |
| 2 | 1 | b |
| 3 | 1 | c |
| 4 | 2 | d |
| 5 | 2 | e |
| 6 | 1 | f |
--------------------------
Table 2 ("followers")
----------------------------
| RowID | LineID | UserID |
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 3 | 1 |
| 4 | 3 | 2 |
| 5 | 2 | 2 |
| 6 | 6 | 1 |
----------------------------
I tried using:
SELECT title
FROM `lines`
LEFT JOIN follow
ON follow.user_id = lines.user_id
WHERE follow.user_id = 1
That ended up producing duplicate rows.
The output I need would ideally be an array consisting of all the lineID's and Titles associated with that userID.
select LineId, Title
from owners
where LineId in (select LineId from followers group by LineId )
order by owners.LineId