count equal fields of 2 Tables and Inner join with 3rd - mysql

I have 3 tables
Table cases: docket is pk
| docket | dt_file |
-----------------------
|AA-0322 | 01-22-2015 |
|AA-0431 | 03-21-2014 |
Table parties:
| id | docket | name |
----------------------------
| 1 | AA-0322 | Bob |
| 2 | AA-0322 | John |
Table motions:
| id | docket | motion |
-----------------------------
| 1 | AA-0322 | Summons|
| 2 | AA-0322 | Guilty |
I want to count the number of fields in parties and motion that have the same docket and then make a table with table.cases with the dt_file
example:
| docket | party_count | motion_count| dt_file |
-----------------------------------------------
AA-0322| 2 | 2 | 02-22-2015|
I also want to filter by dt_file, so adding a WHERE statement ex:
WHERE YEAR(dt_file) = '2015'
So far i've came up with this, but I havn't had success joining table.cases with dt_file correctly.
SELECT p.docket, p.party_count, m.motion_count
FROM
(SELECT docket, COUNT(docket) AS party_count
FROM parties
GROUP BY docket) AS p
INNER JOIN
(SELECT docket, COUNT(docket) AS motion_count
FROM motions
GROUP BY docket) AS m
ON p.docket = m.docket

Your query seems correct. You just need to add cases to the from clause:
SELECT c.docket, p.party_count, m.motion_count, c.dt_file
FROM cases c JOIN
(SELECT docket, COUNT(docket) AS party_count
FROM parties
GROUP BY docket
) p
ON c.docket = p.docket INNER JOIN
(SELECT docket, COUNT(docket) AS motion_count
FROM motions
GROUP BY docket
) m
ON c.docket = m.docket;
If you want all dockets, even those where there are no motions or parties, then use LEFT JOIN.

Let this be another example.
Select
p.docket,
COUNT(p.docket) As party_count,
COUNT(m.docket) As motion_count,
p.dt_file
From
cases As c
Inner Join parties As p
On c.docket = p.docket
Inner Join motions As m
On c.docket = m.docket
Group By
p.docket,
p.dt_file

Try this:
SELECT p.docket, p.party_count, m.motion_count, c.dt_file
FROM
(SELECT docket, COUNT(docket) AS party_count
FROM parties
GROUP BY docket) AS p
INNER JOIN
(SELECT docket, COUNT(docket) AS motion_count
FROM motions
GROUP BY docket) AS m
ON p.docket = m.docket
INNER JOIN cases c
ON p.docket = c.docket
WHERE YEAR(c.dt_file) = '2015'

Related

sql to find number of attendees (joined) of an event

I'm trying to find number of attendees who have actually joined the sessions of the event. I've 5 tables.
event -> day -> session
attendee
session_attendee
Schema
+------------------------------+
| attendee |
+------------------------------+
| id username password |
| 1 user1 test |
| 2 user2 test |
| ------ |
| event |
| id name |
| 1 event 1 |
| 2 event 2 |
| ----- |
| day |
| id date event_id |
| 1 '2015-06-01' 1 |
| 2 '2015-06-02' 1 |
| 3 '2015-07-01' 2 |
| 4 '2015-07-02' 2 |
| ------ |
| session |
| id name day_id |
| 1 session a 1 |
| 2 session b 1 |
| 3 session c 2 |
| 4 session d 2 |
| ------ |
| session_attendee |
| id session_id attendee_id |
| 1 1 1 |
| 2 2 1 |
| 3 1 2 |
| 4 2 2 |
+------------------------------+
Expectation
+-----------------------------+
| id name attendees |
+-----------------------------+
| 1 'event 1' 2 |
| 2 'event 2' 0/null etc. |
+-----------------------------+
Subquery
SQL query I've tried using Joins but it's returning more than one record (i.e. I can't use it as a subquery)
SELECT count(*) FROM event
INNER JOIN day ON event.id = day.event_id
INNER JOIN session ON day.id = session.day_id
INNER JOIN session_attendee ON session.id = session_attendee.session_id
WHERE event.id = 1
GROUP BY attendee_id
Parent Query
with above subquery substituted
SELECT id, name,
(SELECT COUNT(*) FROM day WHERE day.event_id = event.id) AS days,
(SELECT COUNT(*) FROM event
INNER JOIN day ON event.id = day.event_id
INNER JOIN session ON day.id = session.day_id
INNER JOIN session_attendee ON session.id = session_attendee.session_id
GROUP BY session_attendee.attendee_id) AS attendees
FROM event;
SQL Fiddle
http://sqlfiddle.com/#!9/72ffc
More Work:
SELECT event.id, event.name,
(SELECT count(*) FROM event e INNER JOIN day AS d ON e.id = d.event_id WHERE e.id = event.id) AS total_days,
day.date, session.name, session_attendee.attendee_id
FROM event
LEFT JOIN day ON event.id = day.event_id
LEFT JOIN session ON day.id = session.day_id
LEFT JOIN session_attendee ON session.id = session_attendee.session_id
ORDER BY event.id;
-- COUNT(distinct attendee_id) AS attendees
As soon as I enter COUNT(distinct attendee_id), my result set gets reduced to one row, i.e. I don't get to see records for other events.
Your first query looks basically right with one exception: if you want information for an event, you should aggregate by the event id, not the attendee id:
SELECT e.id, e.name, count(*)
FROM event e INNER JOIN
day d
ON e.id = d.event_id INNER JOIN
session s
ON d.id = s.day_id INNER JOIN
session_attendee sa
ON s.id = sa.session_id
GROUP BY e.id;
Of course, if you want information for only one event, you can replace the GROUP BY with:
WHERE e.id = 1
EDIT:
You want a LEFT JOIN to keep all the events:
SELECT e.id, e.name, count(distinct sa.attendee_id)
FROM event e LEFT JOIN
day d
ON e.id = d.event_id LEFT JOIN
session s
ON d.id = s.day_id LEFT JOIN
session_attendee sa
ON s.id = sa.session_id
GROUP BY e.id;
Try this
SELECT event.id, name,
(SELECT COUNT(*) FROM day WHERE day.event_id = event.id) AS days,
b.number_of_attendee
FROM event
left join (
SELECT a.id, count(*) as number_of_attendee from
(
SELECT event.id, attendee_id FROM event
INNER JOIN day ON event.id = day.event_id
INNER JOIN session ON day.id = session.day_id
INNER JOIN session_attendee ON session.id = session_attendee.session_id
group by event.id, attendee_id
) as a
group by a.id) as b
on b.id = event.id
which has the result like
id name days number_of_attendee
1 Event 1 2 2
2 Event 2 2 (null)

adding different columns in same table usin inner join in mysql

I want to make a report of time entry of particular projects. I tried below query.
Table1: Projects
id | Name
------------
1 | A
2 | B
Table2: EmployeeTimeEntry
proj | activity |time
----------------------
1 | coding | 5
2 | coding | 2
1 | testing | 2
1 | coding | 2
My desired Outpput for proj A:
proj | TotalDur | activity | Activitytime
--------------------------------------------
A | 9 | coding | 7
A | 9 | testing | 2
My Query :
$query = "SELECT
name as 'Proj',
TimeEntry.Total as 'TotalDur',
ATimeEntry.ADetails as 'activity',
ATimeEntry.ATotal as 'Activitytime'
FROM Projects pr
INNER JOIN(SELECT project,SUM(time) as Total from EmployeeTimeEntry group by project ) TimeEntry on pr.id = TimeEntry.project
INNER JOIN(SELECT project,details as ADetails,SUM(time) as ATotal from EmployeeTimeEntry where id = pr.id group by details ) ATimeEntry on pr.id = TimeEntry.project";
But i got output as
proj | TotalDur | activity | Activitytime
--------------------------------------------
A | 9 | coding | 9
A | 9 | testing | 2
All activity times for all projects get added .
I use combobo to select which projects to show the report.
I think you are over complicating it
select
p.name as Proj,
x.TotalDur,
et.activity,
sum(et.time) as Activitytime
from Projects p
join (
select proj, sum(time) as TotalDur from EmployeeTimeEntry group by proj
)x on x.proj = p.id
join EmployeeTimeEntry et on et.proj = p.id
where p.name = 'A'
group by p.name,et.activity
DEMO
Maybe this is what you want?
select
p.Name as Proj,
(select sum(time) as TotalDur from EmployeeTimeEntry where proj = p.id group by proj) TotalDur,
activity,
sum(e.time) as ActivityTime
from Projects p
inner join EmployeeTimeEntry e on e.proj = p.id
where p.Name = 'A'
group by name, activity, p.id
Sample SQL Fiddle

MySQL show relations MANY-MANY by condition

There are two tables:
partner
id | name
--------------
1 | partner_1
2 | partner_2
3 | partner_3
4 | partner_4
contract
id | name | is_active
---------------------------
1 | contract_1 | 1
2 | contract_2 | 0
3 | contract_3 | 1
4 | contract_4 | 0
5 | contract_5 | 0
There is a third table that relates the previous two tables with many-to-many relationship
partner_contract
partner_id | contract_id
------------------------
1 | 1
1 | 2
2 | 3
2 | 2
2 | 4
3 | 5
Each partner can have several contracts, among which ONLY ONE can be active and some inactive .
Also the partner may not have contract at all.
I need a query that displays all the partners together with the active contract. If partner dont' have an active contract, display NULL.
partner_id | partner_name | contract_name
-----------------------------------------
1 | partner_1 | contract_1
2 | partner_2 | contract_3
3 | partner_3 | NULL
4 | partner_4 | NULL
I found a solution, but it seems to me that it is not perfect .
SELECT
p.id AS partner_id,
p.name AS partner_name,
active_contract.name AS contract_name
FROM partner p
LEFT JOIN (
SELECT *
FROM contract c
LEFT JOIN partner_contract pc on pc.contract_id = c.id
WHERE c.is_active = 1
) active_contract
ON active_contract.partner_id = p.id
Is there a more elegant solution?
Ray's (deleted) query is close to the right solution. The condition on the contract should go in the on clause, not the where clause:
SELECT p.id AS partner_id, p.name AS partner_name, c.name AS contract_name
FROM partner p LEFT JOIN
partner_contract pc
ON p.id = pc.partner_id LEFT JOIN
contract c
ON pc.contract_id = c.id AND c.is_active = 1;
EDIT:
Okay, the above is wrong. This can be fixed with a group by:
SELECT p.id AS partner_id, p.name AS partner_name, MAX(c.name) AS contract_name
FROM partner p LEFT JOIN
partner_contract pc
ON p.id = pc.partner_id LEFT JOIN
contract c
ON pc.contract_id = c.id AND c.is_active = 1
GROUP BY p.id, p.name;
The more elegant solution (in my opinion):
SELECT p.*,
(select name
from partner_contract pc join
contract c
on pc.contract_id = c.id AND c.is_active = 1
where p.id = pc.partner_id
) as contract_name
FROM partner p;
SQL Fiddle
This can take advantage of indexes and does not require aggregation.

getting latest data in one to many relation table

i would like to fetch data from table a,b,c but order by most recent data of table response
table casework has this structure ( simplified):
casework_id | problem | user_id
------------+-----------+-------
1 | Problem1 | 1
2 | Problem2 | 2
3 | Problem3 | 1
4 | Problem4 | 3
table user has this structure ( simplified):
user_id | name
--------+-----------------
1 | peter
2 | Sam
3 | Tom
4 | Steve
table response has this structure ( simplified):
response_id | response | casework_id | created
------------+-----------+--------------+-------
1 | responce1 | 1 | 2012-10-14 11:28:31
2 | responce2 | 1 | 2012-9-10 11:28:31
3 | responce3 | 1 | 2012-9-2 11:28:31
4 | responce4 | 3 | 2012-8-3 11:28:31
4 | responce5 | 3 | 2012-8-2 11:28:31
I am looking the query to fetch data order by latest responce and group by casework_id
I. e. required out put is
casework_id | problem | name | responce | created
------------+-----------+-------+-----------+---------
1 | Problem1 | peter | responce1 | 2012-10-14 11:28:31
2 | Problem2 | Sam | Null | Null
3 | Problem3 | peter | responce4 | 2012-8-3 11:28:31
4 | Problem4 | Tom | Null | Null
I would be most grateful if one of you kind people could point me in the right direction.
You can use the following:
select c.casework_id,
c.problem,
u.name,
r2.response,
r1.created
from casework c
left join user u
on c.user_id = u.user_id
left join
(
select max(created) created, casework_id
from response r
group by casework_id
) r1
on c.casework_id = r1.casework_id
left join response r2
on r1.created = r2.created
and r1.casework_id = r2.casework_id
See SQL Fiddle with Demo
If you want to include both the user that created the casework and then who responsed, then you will want to join on the user table twice:
select c.casework_id,
c.problem,
u1.name CreatedByName,
r2.response,
r1.created,
u2.name ReponseName
from casework c
left join user u1
on c.user_id = u1.user_id
left join
(
select max(created) created, casework_id
from response r
group by casework_id
) r1
on c.casework_id = r1.casework_id
left join response r2
on r1.created = r2.created
and r1.casework_id = r2.casework_id
left join user u2
on r2.user_id = u2.user_id
See SQL Fiddle with demo
I have not tested it, but it might give you an idea
select c.casework_id, c.problem,
(select name from user u where u.user_id = c.user_id ),
(select r.reponse from response r where r.casework_id = c.casework_id ORDER BY r.created DESC LIMIT 1),
(select r.created from response r where r.casework_id = c.casework_id ORDER BY r.created DESC LIMIT 1),
from casework c
SELECT responce.casework_id, problem, name, responce, created
FROM responce
JOIN
(SELECT casework_id, problem, name
FROM casework JOIN user
ON casework.userid=user.userid) AS A
ON responce.casework_id=A.casework_id
ORDER BY responce, responce.casework_id
Try this
select c.caseword_id, c.problem, u.name, response.response, responce.created from asework c inner join user u on u.user_id = c.user_id left outer join select casework_id from response having max(created) group by casework_id) responsedata on responsedata.casework_id = c.casework_id

LEFT JOIN 3 columns to get username

I have three columns I need to join which comes from 3 different tables,
Contributions table:
+-----------+---------------------+
| record_id | contributor_user_id |
+-----------+---------------------+
| 1 | 2 |
+-----------+---------------------+
| 1 | 5 |
+-----------+---------------------+
Members table:
+--------------+---------+
| username | user_id |
+--------------+---------+
| Test | 1 |
+--------------+---------+
| Test2 | 5 |
+--------------+---------+
| Test3 | 6 |
+--------------+---------+
Records table:
+---------+-----------+
| user_id | record_id |
+---------+-----------+
| 28 | 1 |
+---------+-----------+
For what I need to return is the username and user_id for displaying the record owner. Also, display the username and the user_id, but this can be multiple (more than 1+ user). I've tried this:
SELECT usr.username,
usr.user_id,
rec.record_id,
contrib.record_id,
contrib.contributor_user_id
FROM
(
records rec
INNER JOIN members usr ON rec.user_id = usr.user_id
# this returns records as NULL
LEFT OUTER JOIN contributions contrib ON rec.record_id = contrib.record_id AND contrib.contributor_user_id = usr.user_id
# this works, but I need the username to be displayed too
LEFT OUTER JOIN contributions contrib ON rec.record_id = contrib.record_id
)
WHERE rec.record_id = 1
Try nesting the join for contributing users inside of the left join to contributions.
SELECT u.username, u.user_id, r.record_id, u2.username as ContributorName, u2.user_id as ContributorId
FROM records r
INNER JOIN members u
ON r.user_id = u.user_id
LEFT JOIN contributions c
INNER JOIN members u2
ON c.contributor_user_id = u2.user_id
ON r.record_id = c.record_id
WHERE r.record_id = 1
SELECT
usr.username AS record_owner
, usr.user_id AS record_owner_id
, rec.record_id
, con.contributor_user_id AS contributor_id
, contributors.username AS contributor_name
FROM
records rec
INNER JOIN
members usr
ON rec.user_id = usr.user_id
LEFT OUTER JOIN
contributions con
ON rec.record_id = con.record_id
INNER JOIN
members contributors
ON con.contributor_user_id = contributors.user_id
WHERE
rec.record_id = 1