I am having some problem with getting the values from two tables of my database .
I have two tables in my database 1 is mem and 2nd is payment
mem stores name and drawid of users
payment table stores draw and instalment of the user
User pays us every month .
so if a user with a draw id 1 pays us in feb the values in two tables are
mem drawid=1 and name = something
payment draw = 1 and instalment=2
drawid in mem is same as draw in payment
so the tables has many to many relation.
Now I need to find the list of all the members who have not paid even 1 instalment before 4th month.
I am using this query
SELECT drawid,contact,dnd,mem.name, count(*) as numPayments FROM mem
LEFT JOIN payment ON (mem.drawid = payment.draw) GROUP BY
drawid HAVING numPayments < 4
it's working all good no issues only the issue is that I also need to show the instalments the user has paid so I need to fetch all the instalment from table payments and then show by while loop.
This query is perfect but it gives me repeated results !!!
SELECT drawid,contact,dnd,mem.name, count(*) as numPayments,NULL numPaidPayments ,NULL PAID_CONTACT,NULL NAME_PAID FROM mem
LEFT JOIN payment ON (mem.drawid = payment.draw) GROUP BY
drawid HAVING numPayments < 4
UNION
SELECT NULL drawid,NULL contact, NULL dnd, NULL name,NULL numPayments,COUNT(*) as numPaidPayments ,contact PAID_CONTACT,mem.name NAME_PAID FROM mem
INNER JOIN payment ON (mem.drawid = payment.draw) GROUP BY
drawid HAVING numPaidPayments >= 4
SELECT drawid,contact,dnd,mem.name, count(*) as numPayments,NULL numPaidPayments ,NULL PAID_CONTACT,NULL NAME_PAID FROM mem
LEFT JOIN payment ON (mem.drawid = payment.draw) GROUP BY
drawid HAVING numPayments < 4
UNION
SELECT NULL drawid,NULL contact, NULL dnd, NULL name,NULL numPayments,COUNT(*) as numPaidPayments ,contact PAID_CONTACT,mem.name NAME_PAID FROM mem
INNER JOIN payment ON (mem.drawid = payment.draw) GROUP BY
drawid HAVING numPaidPayments >= 4
Try above query.
Given this
MariaDB [sandbox]> select * from member;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
+------+
4 rows in set (0.00 sec)
MariaDB [sandbox]> select * from payment;
+--------+------+
| mem_id | mth |
+--------+------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 1 |
| 2 | 3 |
| 3 | 2 |
| 3 | 4 |
+--------+------+
8 rows in set (0.00 sec)
This
select m.id, group_concat(p.mth order by p.mth) mthspaid,
sum(case when p.mem_id is not null then 1 else 0 end) NoofMthsPaid,
4 - sum(case when p.mem_id is not null then 1 else 0 end) NoofMthsMissed
from member m
left join payment p on p.mem_id = m.id
group by m.id
Gives this
+------+----------+--------------+----------------+
| id | mthspaid | NoofMthsPaid | NoofMthsMissed |
+------+----------+--------------+----------------+
| 1 | 1,2,3,4 | 4 | 0 |
| 2 | 1,3 | 2 | 2 |
| 3 | 2,4 | 2 | 2 |
| 4 | NULL | 0 | 4 |
+------+----------+--------------+----------------+
4 rows in set (0.00 sec)
And if you add in code to work out the months due
select paid.*, due.mthsmissed
from
(
select m.id, group_concat(p.mth order by p.mth) mthspaid,
sum(case when p.mem_id is not null then 1 else 0 end) NoofMthsPaid,
4 - sum(case when p.mem_id is not null then 1 else 0 end) NoofMthsMissed
from member m
left join payment p on p.mem_id = m.id
group by m.id
) paid
left join
(
select due.id, group_concat(due.mth order by due.mth) MthsMIssed
from
(
select m.id,d.mth
from member m,(select 1 mth union select 2 union select 3 union select 4) d
) due
left join payment p on p.mem_id = due.id and p.mth = due.mth
where p.mth is null
group by due.id
) due on paid.id = due.id
You get this
+------+----------+--------------+----------------+------------+
| id | mthspaid | NoofMthsPaid | NoofMthsMissed | mthsmissed |
+------+----------+--------------+----------------+------------+
| 1 | 1,2,3,4 | 4 | 0 | NULL |
| 2 | 1,3 | 2 | 2 | 2,4 |
| 3 | 2,4 | 2 | 2 | 1,3 |
| 4 | NULL | 0 | 4 | 1,2,3,4 |
+------+----------+--------------+----------------+------------+
4 rows in set (0.04 sec)
Related
I have three tables, two of which are relevant for this question. Users, Things, User_to_thing
Users
ID | Name | Active
-------------------
1 | Joe | 1
2 | Jack | 1
3 | Tom | 1
4 | Harry | 0
5 | Stan | 1
6 | Bob | 1
User_to_thing
Thing ID | User ID | Status
---------------------------
3 | 1 | 1
3 | 2 | 2
3 | 5 | 1
4 | 1 | 3
4 | 2 | 2
I'm trying to create a query where I can select all the active users in the users table and have a column where I can see the status for "thing 3" from the User_to_thing table while also sorting results so that the nulls come at the end. So the result would be something like:
User ID | Status
----------------
1 | 1
2 | 2
5 | 1
3 | NULL
6 | NULL
What I have so far for a query is the following:
SELECT u1.id, u1.name, user_to_thing.status
FROM users u1
LEFT JOIN user_to_thing ON u1.id = user_to_thing.user_id
WHERE u1.active = 1
OR user_to_thing.event_id = 62
ORDER BY (CASE WHEN user_to_thing.status = 1 THEN 1
WHEN user_to_thing.status = 2 THEN 2
ELSE 3 END)
What I'm getting as a result is the following:
User ID | Status | Thing ID
---------------------------
1 | 1 | 3
1 | 3 | 4
2 | 2 | 3
2 | 2 | 4
5 | 1 | 3
3 | NULL | NULL
6 | NULL | NULL
I'm not sure how to limit it to just thing #3 while also getting a list of all active users. Any guidance would be appreciated.
It looks like the following should work for you, grouping to remove duplicates and ordering based on null
select u.Id as UserId, t.status
from users u
left join User_to_thing t on t.UserID = u.id
where u.active = 1
group by u.Id, t.Status
order by case when status is null then 1 else 0 end, u.Id
Based on your revised data, you can amend slightly
select u.Id UserId, Min(t.status) Status
from users u
left join User_to_thing t on t.UserID=u.id
where u.active=1
group by u.Id
order by case when Min(t.status) is null then 1 else 0 end, u.Id
My table is this.
users_table:
id | name | admin | property_id
-----------------------------------
1 | x | 1 | 0
2 | y | 1 | 0
3 | z | 0 | 1
4 | t | 0 | 2
4 | u | 0 | 2
4 | o | 0 | 2
I have two records which are admin and some other records which belong to one of these two records by matching the property_id with the id.
In the end what I want is the admin row data and the count of its properties.
The problem is that the data is all in the same table.
This is what should be the output from the desired query.
id | name | admin | property_count
-----------------------------------
1 | x | 1 | 1
2 | y | 1 | 3
http://sqlfiddle.com/#!9/5ad1fb/4
SELECT u.*, COUNT(ut.id) property_count
FROM users_table u
LEFT JOIN users_table ut
ON u.id = ut.property_id
WHERE u.admin = 1
GROUP BY u.id, u.name, u.admin
You seem to want a self-join and aggregation:
select t1a.id, t1a.name, t1a.admin, count(t1.id) as property_count
from table1 t1a left join
table1 t1
on t1a.id = t1.property_id
where t1a.admin = 1
group by t1a.id, t1a.name, t1a.admin;
There is, incidentally, a trickier way to do this without a join:
select (case when admin = 1 then id else property_id end) as id,
max(case when admin = 1 then name end) as name,
max(admin) as admin,
sum( admin <> 1 ) as property_count
from table1 t1
group by (case when admin = 1 then id else property_id end);
I don't know how to explain the scenario using words. So am writing the examples:
I have a table named tblType:
type_id | type_name
---------------------
1 | abb
2 | cda
3 | edg
4 | hij
5 | klm
And I have another table named tblRequest:
req_id | type_id | user_id | duration
-------------------------------------------
1 | 4 | 1002 | 20
2 | 1 | 1002 | 60
3 | 5 | 1008 | 60
....
So what am trying to do is, fetch the SUM() of duration for each type, for a particular user.
This is what I tried:
SELECT
SUM(r.`duration`) AS `duration`,
t.`type_id`,
t.`type_name`
FROM `tblRequest` AS r
LEFT JOIN `tblType` AS t ON r.`type_id` = t.`type_id`
WHERE r.`user_id` = '1002'
GROUP BY r.`type_id`
It might return something like this:
type_id | type_name | duration
-------------------------------
1 | abb | 60
4 | hij | 20
It works. But the issue is, I want to get 0 as value for other types that doesn't have a row in tblRequest. I mean I want the output to be like this:
type_id | type_name | duration
-------------------------------
1 | abb | 60
2 | cda | 0
3 | edg | 0
4 | hij | 20
5 | klm | 0
I mean it should get the rows of all types, but 0 as value for those type that doesn't have a row in tblRequest
You could perform the aggregation on tblRequest and only then join it, using a left join to handle missing rows and coalesce to convert the nulls to 0s:
SELECT t.type_id, type_name, COALESCE(sum_duration, 0) AS duration
FROM tblType t
LEFT JOIN (SELECT type_id, SUM(duration) AS sum_duration
FROM tblRequest
WHERE user_id = '1002'
GROUP BY type_id) r ON t.type_id = r.type_id
Select a.type_id, isnull(sum(b.duration), 0)
From tblType a Left Outer Join tblRequest b
ON a.type_id = b.type_id and b.user_id = 1002
Group by a.type_id
I have those tables:
Members
---------------------------
MemberID | Name |.....
1
2
3
4
---------------------------
RentedMovies
---------------------------
MemberID | MovieID | DateOfLease | ReturnDate | .....
1 | 1 | 2012-12-20 | 2013-01-05
1 | 2 | 2012-12-15 | 2012-12-30
1 | 3 | 2012-12-16 | 2013-01-06
2 | 1 | 2012-12-17 | 2012-12-18
2 | 4 | 2012-12-18 | 2013-01-05
3 | 1 | 2012-12-19 | 2013-01-04
I need to get this:
--------------------------------------------------------
MemberID | NumberOfRentedMovies | ReturnData < curdate())
1 | 3 | 1
2 | 2 | 1
3 | 1 | 0
4 | 0 | 0
---------------------------------------------------------
And i used next code:
SELECT Members.MemberID,
COUNT(rented.MemberID) AS NumberOfRentedMovies,
COUNT(notTakenBackOnTime.idClana) AS NumberOfMoviesLate
FROM Members
left JOIN RentedMovies as rented ON rented.MemberID = Members.MemberID
left JOIN RentedMovies as notTakenBackOnTime ON notTakenBackOnTime.MemberID
= Members.MemberID AND notTakenBackOnTime.ReturnDate< CURDATE()
group by Members.MemberID
But it doesnt work corrextly!
And I also tried with this:
SELECT MemberID,my,my2
FROM Members as mem
JOIN (SELECT COUNT(* )AS my FROM RentedMovies) b
ON b.MemberID = mem.MemberID
JOIN (SELECT COUNT(* )AS my2 FROM RentedMovies WHERE ReturnDate< CURDATE()) c
ON c.MemberID = mem.MemberID
But i got some errors!
So the question is how to accomplish right solution?
You were close. Try this:
SELECT M.MemberID,
COUNT(RM.MemberID) NumberOfRentedMovies,
SUM(CASE WHEN RM.ReturnDate < CURDATE() THEN 1 ELSE 0 END) ReturnData
FROM Members M
LEFT JOIN RentedMovies RM
ON M.MemberID = RM.MemberID
GROUP BY M.MemberID
The desired result you showed can be accomplished by:
SELECT MemberID,
COALESCE(COUNT(MovieID), 0) AS NumberOfRentedMovies,
COALESCE(SUM(ReturnDate < CURDATE()), 0) AS NotYetReturned
FROM Members
LEFT JOIN RentedMovies USING (MemberID)
GROUP BY MemberID
See it in action: http://sqlfiddle.com/#!2/a192c/1
Let's say I have 2 tables.
The first table is a list of personas. A user can have many personas.
mysql> select id, user_id, name from personas_personas;
+----+---------+--------------+
| id | user_id | name |
+----+---------+--------------+
| 8 | 1 | startup |
| 9 | 1 | nerd |
| 10 | 1 | close |
| 12 | 2 | Nerd |
| 13 | 2 | Startup |
| 14 | 2 | Photographer |
+----+---------+--------------+
6 rows in set (0.00 sec)
Now, I have another table called "approvals".
mysql> select id, from_user_id, to_user_id, persona_id from friends_approvals;
+----+--------------+------------+------------+
| id | from_user_id | to_user_id | persona_id |
+----+--------------+------------+------------+
| 2 | 1 | 2 | 8 |
| 3 | 1 | 2 | 9 |
+----+--------------+------------+------------+
2 rows in set (0.00 sec)
If from_user wants to approve to_user to a persona, then a record is inserted.
I'm trying to do this query...
Given a user, find all its personas. Then, for each persona, determine if it's approved for a certain to_user. If so, return is_approved=1 in the result set. Otherwise, return is_approved=0 in the result set.
So this is where I start:
SELECT *
FROM personas_personas
WHERE user_id = 1
LEFT JOIN friends_approvals ON
...but i don't know where to go from here.
So, the final result set should have all the columns in the personas_personas table, and then also is_approved for each of the results.
SELECT
pp.*,
CASE
WHEN exists (
SELECT
*
FROM
friends_approvals fa
WHERE
fa.from_user_id = pp.user_id AND
fa.persona_id = pp.id AND
fa.to_user_id = 2
)
THEN 1
ELSE 0
END as is_approved
FROM
personas_personas pp
WHERE
pp.user_id=1
Or, depending on your taste:
SELECT
pp.*,
CASE
WHEN fa.from_user_id IS NOT NULL
THEN 1
ELSE 0
END as is_approved
FROM
personas_personas pp
LEFT OUTER JOIN friends_approvals fa ON
pp.user_id = fa.from_user_id AND
pp.id = fa.persona_id AND
fa.to_user_id = 2
WHERE
pp.user_id=1
If I'm understanding your needs correctly, you can do this:
SELECT personas_personas.*,
CASE WHEN friends_approvals IS NULL THEN 0 ELSE 1 END AS is_approved
FROM personas_personas
LEFT
OUTER
JOIN friends_approvals
ON friends_approvals.from_user_id = ...
AND friends_approvals.to_user_id = personas_personas.user_id
AND friends_approvals.persona_id = personas_personas.id
WHERE personas_personas.user_id = ...
;
That will find every personas_personas record with the specified user_id, together with an indicator of whether that user, in that persona, has been "approved" by a specified from_user_id.
(If that's not what you want, then please clarify!)