Php MySQL Many to Many to Many condition Group By - php

I am creating a query between multiple many to many relationship tables in order to chain their values together. My issue is that I can't seem to figure a way to Group By the 'service' values from the 'services' sub-table in this query:
SELECT
GROUP_CONCAT(containers.container_id ORDER BY containers.container_id DESC) AS container_id,
GROUP_CONCAT(containers.container_serial ORDER BY containers.container_id DESC) AS container_serial,
GROUP_CONCAT(containers.container_index ORDER BY containers.container_id DESC) AS container_index,
invoices.*,
statuses.status,
clients.client,
GROUP_CONCAT(services.service_id ORDER BY containers.container_id DESC) AS service_id,
GROUP_CONCAT(services.service ORDER BY containers.container_id DESC) AS service
FROM containers_invoices
LEFT JOIN containers
ON containers_invoices.container_id = containers.container_id
LEFT JOIN invoices
ON containers_invoices.invoice_id = invoices.invoice_id
LEFT JOIN statuses
ON invoices.status_id = statuses.status_id
LEFT JOIN clients
ON invoices.client_id = clients.client_id
LEFT JOIN invoices_services
ON invoices.invoice_id = invoices_services.invoice_id
LEFT JOIN services
ON invoices_services.service_id = services.service_id
GROUP BY containers_invoices.invoice_id
ORDER BY invoice_id DESC
Right now my result looks something like this:
C09-65475u76u76, C08-dfsgreg345g3 - 114 - ? - Service,Service - 1000 - Sent
C09-65475u76u76, C08-dfsgreg345g3, C03-dfsdfsd, C02-sadasd - 117 - ? - Line,Line,Line,Line - 3000 - Paid
The service should show up only once and not loop as many times as the containers number that I have. I know I am close, but I can't seem to close that solution gap. Thanks for your help!

You are grouping by invoice:
GROUP BY containers_invoices.invoice_id
You should group by service from what I understand
GROUP BY services.service_id
EDIT: I guess I misunderstood the question. You'd like to keep one row per invoice but in your group_concat not list mutliple times the same value.
If it is so, you can use the DISTINCT keyword:
GROUP_CONCAT(DISTINCT services.service ORDER BY containers.container_id DESC) AS service

Related

MYSQL show uncounted

I've two tables in MySQL: tracks and ratings. I want the query to count how much ratings there are per track, that's why I use the following:
SELECT t.*, COUNT(*) as ratings
FROM tracks t, ratings r
WHERE t.trackID = r.trackID
GROUP BY t.trackID
ORDER BY ratings DESC
Well my problem now is, that when a track doesn't have a rating yet (so count is 0) it won't show, but I also want it to show when there aren't any ratings yet. I hope someone can help me. Thanks in advance! Steven.
Try this, hope you'll find it helpful.
SELECT t.*, (select count(*) from ratings r where r.trackID = t.trackID) as ratingsCount from tracks t order by ratingsCount DESC;
You must use LEFT JOIN to preserve all left side (i.e. tracks) records.
SELECT t.*, COUNT(*) as ratings
FROM tracks t
LEFT JOIN ratings r
ON t.trackID = r.trackID
GROUP BY t.trackID
ORDER BY ratings DESC

SQL count with two table

was wondering if someone could help a newbie out with some sql?
Right so basically I want to get all the CustomerID's associated with a certain countrycode I can get that by doing a simple query on the customer table however I then need to find out how many forms the customer has submitted in the order table.
so in summary I need to get a list of customerID's from the Customer table and count how many time they show up in the Order table.
What's the easiest way to go about this?
P.S. please ignore any data type / relationship issues with the image above, it's just an example.
Thanks.
Join the tables, filter on country code and group the results:
SELECT CustomerID, COUNT(*)
FROM query_test.customer JOIN query_test.Order USING (CustomerID)
WHERE query_test.customer.countrycode = ?
GROUP BY CustomerID
You could use
SELECT
c.customerID,
count(o.form_id) AS form_count
FROM
customer c INNER JOIN order o
ON c.customerID = o.customerID
WHERE
c.countrycode = ??
GROUP BY
c.customerID
If you have customers that don't have any orders, then you will want a left outer join:
SELECT c.CustomerID, COUNT(o.CustomerID) as NumOrders, COUNT(distinct FormID) as NumForms
FROM query_test.customer c LEFT JOIN
query_test.Order o
on c.CustomerID = o.CustomerId
WHERE c.countrycode = ?
GROUP BY c.CustomerID;
Note this counts both the number of orders and the number of forms.

MySQL query giving duplicate results

I am querying four tables (activities, notes, categories, user_entries) looking for matches that are EITHER activities OR notes. In my development database, I have 8 activities and 2 notes that match: instead I get 16 results. Each activity is duplicated: one result including the first note, the other including the second.
This is the query as it stands:
SELECT a.`aid`, a.`activityname`, a.`date`, u.`points`, u.`enid`, c.`catname`, n.`nid`, n.`notename`, n.`dates`
FROM activities a
INNER JOIN user_entries u ON a.`aid` = u.`aid_FK`
INNER JOIN categories c ON a.`category` = c.`cat`
INNER JOIN notes n ON u.`mem_no_FK` = n.`mem_no_FK`
WHERE u.`mem_no_FK` = 1995
GROUP BY a.`aid`, a.`activityname`, a.`date`, u.`points`, u.`enid`, c.`catname`, n.`nid`, n.`notename`, n.`dates`
ORDER BY `date`
I have looked at quite a few similar questions here, (especially question 7696248): but nothing I've tried has worked. Despite trying many suggestions (with/without DISTINCT, with/without GROUP BY, many join types, etc.) I get the same result each time: there is something basically wrong with the query. My knowledge of SQL is not good and I don't know how to fix it.
Can anyone help?
EDIT: FOR CLARITY
The database is a record of continuing professional development activities. Notes (confusingly named, but not by me!) are not linked to activities: they are there for users to record significant events- "No CPD done for 3 months due to road accident", and so on.
I need to list the notes and the activities on the same page: if it's possible, I'd prefer to run one DB query; if it isn't, I'll have to run two queries and amalgamate the two results arrays.
Please try DISTINCT for aid
SELECT DISTINCT(a.`aid`), a.`activityname`, a.`date`, u.`points`, u.`enid`, c.`catname`, n.`nid`, n.`notename`, n.`dates`
FROM activities a
INNER JOIN user_entries u ON a.`aid` = u.`aid_FK`
INNER JOIN categories c ON a.`category` = c.`cat`
INNER JOIN notes n ON u.`mem_no_FK` = n.`mem_no_FK`
WHERE u.`mem_no_FK` = 1995
GROUP BY a.`aid`, a.`activityname`, a.`date`, u.`points`, u.`enid`, c.`catname`, n.`nid`, n.`notename`, n.`dates`
ORDER BY `date`
If you want to select all notes in one column you can use GROUP_CONCAT or other aggregate functions
SELECT a.`aid`, a.`activityname`, a.`date`, u.`points`, u.`enid`, c.`catname`, GROUP_CONCAT(n.`notename` SEPARATOR ' ') as notes
FROM activities a
JOIN user_entries u ON a.`aid` = u.`aid_FK`
JOIN categories c ON a.`category` = c.`cat`
JOIN notes n ON u.`mem_no_FK` = n.`mem_no_FK`
WHERE u.`mem_no_FK` = 1995
GROUP BY a.`aid`
ORDER BY `date`

MYSQL Join help. Get results based on number of comments in seperate comments table?

Beginner here! I am trying to write a query that will select the 3 most commented on results from a "results" table the comments are stored in a seperate "comments" table.
results
- id
- title
- body
- etc
- etc
comments
- id
- result_id
- user_id
- timestamp
- comment
So I need to select all from results and order by the amount of matches between results.id and comments.result_id but I don't really know where to start!
Thanks a lot for the help, it's much appreciated!
Not tested but you can do something like that
SELECT r.id ,r.title, r.body
FROM results r INNER JOIN (SELECT result_id, count(id) cnt FROM comments GROUP BY result_id) c
ON r.id = c.result_id
ORDER by c.cnt DESC
Perhaps try something like this:
SELECT COUNT(c.id) AS comment_count FROM results r
LEFT JOIN comments c ON r.id=c.result_id
GROUP BY result_id ORDER BY comment_count DESC LIMIT 3;
The following should work:
SELECT r.id, COUNT(r.id) AS comment_count
FROM results r
INNER JOIN comments c
ON results.id = c.result_id
GROUP BY r.id
ORDER BY comment_count DESC
You join the two tables where the id of the result is the same as the referenced result_id from the comments table. Then you group the rows by result_id to remove duplicates. The COUNT() function sums up the grouped rows and displays the number of them.
Then just sort the result based on the generated comment count.
You could use LEFT OUTER JOIN as well, then you would get all results that have no comments as well. If you want this or not depends on your needs.
For a description of SQL joins, check out What is the difference between "INNER JOIN" and "OUTER JOIN"?

how to do this complex fetch in 1 query?

I have an application with tutors and courses and subscribers and ratings. These are the tables I am using:
tbl_tutors:
id
name
tbl_subscribers:
id
user_id
course_id
tbl_courses:
id
name
tutor_id
tbl_ratings:
id
user_id
course_id
rating
I need to get 1 tutor with the number of courses he has, the number of total subscribers for those courses and the average course rating for all his courses. This is a lot of data; can it be done in 1 sql query or do I need to code foreach statements in php to get the average ratings and the total subscribers for those courses?
Well do you need totals per tutor-course combination or a total (and average) at the tutor level?
And what is the rating table adding over the subscriber table? Aren't they both unique user-course combinations?
If one user attends multiple courses by the same tutor, how many subscribers do they count as?
The SQL provided by #alfasin is easily extended to all tutors. The syntax below is for SQL server, you may need to change for MySQL
Select t.name, count(distinct c.id) courseCount, count(s.id) subscribers, avg(r.rating) subRating
From tbl_tutors t
Inner join tbl_courses c on c.tutorid = t.id
Inner join tbl_subscribers s on s.courseid = c.id
Inner join tbl_ratings r on r.userid = s.userid and r.courseid = c.id
Group by t.name
Note that when trying to build queries like this it's usually best to do them without grouping so you can inspect which rows are contributing to the counts and ensure you're including everything you expect and that you're not duplicating results
select t.name "Tutor", count(c.id) "# courses", count(s.id) "# subscribers"
from tbl_tutors t, tbl_subscribers s, tbl_courses c, tbl_ratings r
where t.id = XXX
and c.tutor_id = t.id
and s.course_id = c.id
and r.user_id = s.user_id
group by t.name
this sql will get you all you need besides the courses average (substitute the XXX with the tutor-id you want to find). for courses average you can run a separate select.

Categories