Formulating a MySql join query with aggregates - mysql

Let's say i've got a database with 4 tables:
users: (personal database)
id
user_name
lessons: (lesson names like math / gym etc.)
id
lesson_name
payments (contains payments with lesson_id and a part of the payment [the whole payment is divided to 12 parts])
id
lesson_id
part
value
groups: (to array users to lessons)
id
lesson_id
user_id
My question is how to query the database to get a table with list of all people attending to for ex. math (or any other lesson_id) with their name (probably LEFT JOIN) and SUM of all the payments for each period. The table header for chosen lesson_id should look like:
username | payment 1 | payment 2 | ...(3-11)... | payment 12
I have no clue how to make this work. Maybe my MySQL approach is innapropriate or i should divide it to more queries for more flexibility.
Thank You for your time!

select users.id, users.user_name,lessons.id, lessons.lesson_name,
(SELECT SUM(value) FROM payments
WHERE payment.lesson_id = lessons.id)
FROM users
INNER JOIN groups ON (groups.user_id = users.id)
INNER JOIN lessons ON (lessons.id = groups.lesson_id)
WHERE .....

Related

Mysql subquery in where clause that returns comma separated value

I'm not really good at subqueries, here's the sample tables that I have.
table customers
=====================
id | name | order_ids
1 | John | 1,2
table orders
=====================
id | name
1 | apple
2 | orange
I'm trying to get the order names using this query, but I'm only getting one result. I'm not sure if this is possible.
select o.name
from orders o
where o.id IN(
select c.order_ids
from customers c
where c.id=1
)
Your primary effort should go into fixing your design. You should not be storing several integer values in a string column. If each order belongs to a single customer, then the customer id should be stored in the orders table. If an order may belong to multiple customers at once, then you need a bridge table, with one row per customer/order tuple.
That said: for you current design, you can use find_in_set():
select o.*
from orders o
inner join customers c on find_in_set(o.id, c.order_ids)
where c.id = 1

SQL - Counting how many associated records another table has

As I'm SQL beginner, I can't describe a problem in a simple way, so let me show you an example:
3 Tables:
PRODUCT
id
group_id
person_id
GROUP
id
name
PERSON
id
group_id
As you see, GROUP can have multiple PERSONs and PRODUCT can be connected with GROUP and PERSON.
From this point, I would like to count number of PERSONs having a PRODUCT within a GROUP
I don't really understand the background of IN or using another SELECT within FROM, so if that's the point, then I'm happy that I was one step before it lol.
SELECT
group.name as GROUP_name,
COUNT(DISTINCT person_id) AS PERSON_having_min_one_PRODUCT
FROM products
LEFT JOIN groups ON groups.id = products.group_id
LEFT JOIN persons ON persons.id = products.person_id;
With this data:
GROUP
ExampleGroupName1 has 3 PERSONs, but 2 of them has >0 PRODUCTS
ExampleGroupName2 has 3 PERSONs and all of them has >0 PRODUCTS
ExampleGroupName3 has 2 PERSONs, but none of them has the PRODUCT
ExampleGroupName4 has 2 PERSONs, but only 1 has >0 PRODUCT
I would like to have an output like this:
GROUP_name | PERSON_having_min_one_PRODUCT
ExampleGroupName1 | 2
ExampleGroupName2 | 3
ExampleGroupName4 | 1
I would like to count number of PERSONs having a PRODUCT within a GROUP
Note: I will assume the table product does not have the column group_id, since it is redundant and can lead to a lot of errors.
The following query will show you the result you want by joining the tables person and product:
select
count(distinct x.id)
from person x
join product p on p.person_id = x.id
where x.group_id = 123 -- choosing a specific group
and p.id = 456 -- choosing a specific product
This would rather be simple like below meaning all the groups with some group_id with count(persons) and those count who has some product via id used in having clause
Select group_id,
count( distinct id ) AS "PERSON_WITH_PRODUCT"
from
person group by group_id having id
in (Select id from product);

MySQL Show records of current user + users that he is a parent of

how do I go about writing the MySQL code to get records of the current logged in user and on top of that, the users that he is a parent of?
user_id | username | parent_user_id
---------+------------+-----------------
1 | alvin | NULL
2 | gary | 1
3 | tom | 1
We log into to the user alvin and have basic MySQL statement... (pseudo code)
This selects orders that belong to Alvin.
SELECT *
FROM orders
WHERE user_id = $_SESSION['loggedUser']
How do I go about writing the Statement that also display orders from Gary and Tom (due to the parent-child relationship defined in the user's table? Or for lack of a better term, like a team leader/team restricted viewing.
*Also like to add that the orders table only stores information and a single username field to store which user the order belongs to
Many thanks!
Try this:
SELECT *
FROM orders
WHERE user_id = $_SESSION['loggedUser']
OR
user_id IN (SELECT user_id
FROM users
WHERE parent_user_id= $_SESSION['loggedUser'])
Try this
SELECT child.user_id,child.username
FROM orders main
left join orders child on child .parent_user_id=main.user_id
WHERE main.user_id = $_SESSION['loggedUser']
This don't have to be complicated (for single level of hierarchy)
SELECT *
FROM orders
WHERE user_id = $_SESSION['loggedUser']
OR parent_user_id = $_SESSION['loggedUser']

Join table on pattern match

I have been struggling with this for several hours, so any feedback or advise is very welcome.
I have three tables:
users
id name email
1 test test#test.com
2 test2 test2#test.com
pets
pet_id pet_name user_id
1 sam 2
2 sally 1
transactions
trans_id custom
1 1
2 pid2
3 pid1
OK, what I would like to do is get transaction data relating to the user. So in the 'transactions' table 'custom' value 1 would relate to 'users' with the id. Thats the simple bit...
'Transactions' with 'pid' relate to the pets id, so 'pid2' relates to sally, whose user is user id 1. So I need to join the transaction table when custom relates to the user id or if its prefixed with 'pid' and the appending value relates to the 'pet_id'.
Here's an example of the result I would like:
Transactions relating to user_id 1:
trans_id 1, custom 1
trans_id 2 custom pid2 (this is because the pets owner is user_id 1)
Here is where I am with my attempt at the moment:
SELECT users.*, transactions.*
FROM users
LEFT JOIN transactions on users.id = transactions.custom
This is where I'm falling over:
SELECT users.*, transactions.*
FROM users
LEFT JOIN pets ON pets.user_id = user.id
LEFT JOIN transactions on (users.id = transactions.custom
OR pets.pet_id REGEXP '^pid(transactions.custom)')
If you can't change the table design and the prefix pid is fixed you could use
OR (
pets.pet_id = SUBSTR(transactions.custom, 3)
AND SUBSTR(transactions.custom, 1 FOR 3) = 'pid')
see documentation to SUBSTR and because MySQL automatically converts numbers to strings as necessary, and vice versa, see: http://dev.mysql.com/doc/refman/5.7/en/type-conversion.html
You HAVE to refactor Your DB. Current structure will guarantee of speed problems.
Table transactions should looks like
CREATE TABLE transactions
(
id Int NOT NULL, (id of transaction)
pet_id Int, (can be null)
user_id Int (can be null)
other columns here...
)
;

Selecting results from 2 tables based on the variables in 3th table

I have 2 tabes in my database:
users - userID(primary key), username, password
courses - id(primary key), name, text
subscriptions - id(primary key), curso_id, user_id
right in the subscription table I am writing the users UserID inside -> user_id with the id of the course for which he is subscribed curso_id so the results in the subscrption database are like
subscribtions table:
id user_id curso_id
1 12 1
2 5 1
3 12 2
4 6 7
this is the users table:
users table
userID username password
1 user1 passw1
2
3
4
and this is the courses table:
course table:
id course_name descriotion
1 course one text
2
3
My question is how to make a sql Query which first select the course by $row['id'] which indicates the id variable from the courses database, and after that based on the 3th table subscription to list all the users which are subscribed to this course number. ?
and second question is how to list number of the subscribed users for a course selected by
$row['id']
Here is some kind of the alghorytm logic that I have right now
SELECT * FROM users WHERE id=5.courses(select from the database 'courses') AND 5-> SELECT ALL FROM table subscriptions user_id equal to id from table users
Not sure if I understood what you try to achieve, but if you want a list that shows you every user in every course with the name of the course and ordered by course name, this should make the deal.
select t1.*, t2.*, t3.* from users as t1, courses as t2, subscriptions as t3 where t3.user_id = t1.userID and t3.curso_id = t2.id order by t2.id
Not the nicest way to do this and from a performance aspect I would recommend to put this in several statements as joins are usually slow.
okay I found the way and here is the mysql query:
FROM users
INNER JOIN subscriptions
ON users.userID = subscriptions.user_id
WHERE subscriptions.curso_id = $ids"