I'm trying to build a query using data from 4 tables: Bookings, Users, Events, Locations
Bookings :
+---------------------------------+
|book_id | event_id | person_id |
+---------------------------------+
|1 | 1 | 2 |
|2 | 2 | 1 |
|3 | 2 | 2 |
|4 | 1 | 3 |
|5 | 3 | 1 |
|6 | 3 | 2 |
+---------------------------------+
Users :
+----------------------+
| user_id | name |
+----------------------+
| 1 | Joe |
| 2 | Jack |
| 3 | Jane |
+----------------------+
Events :
+------------------------+
| event_id | location_id |
+------------------------+
| 1 | 1 |
| 2 | 3 |
| 3 | 1 |
+------------------------+
Locations :
+---------------------------+
| location_id | name |
+---------------------------+
| 1 | Lombard |
| 2 | NYC |
| 3 | LA |
+---------------------------+
The query that I can't seem to write should get me to display a table like this :
+------------------------------+
+Name |Lombard|NYC|LA|Total|
+------------------------------+
+Joe |1 |0 |1 |2 |
+Jack |2 |0 |1 |3 |
+Jane |1 |0 |0 |1 |
+------------------------------+
+Totals |4 |0 |2 |6 |
+------------------------------+
What I got to work is displaying how many booking have been made per user but not per user AND per location using this query:
$query='
SELECT
bookings.person_id,
COUNT(bookings.person_id) AS total,
bookings.event_id,
users.display_name
FROM bookings
INNER JOIN users ON bookings.person_id=users.id
WHERE users.id=bookings.person_id
GROUP BY bookings.person_id';
$result = mysql_query($query);
if($result) {
while($row = mysql_fetch_array($result))
{
/* total bookings per user */
$value = $row['total'];
$sum += $value;
/* Displaying results */
echo "<tr width='500'>";
echo "<td>".$row['person_id']."</td>";
echo "<td>".$row['display_name']."</td>";
echo "<td>".$row['total']."</td>";
echo "</tr>";
}
This works okay and displays :
+-----------------------------------+
| ID | NAME | Total Bookings |
+-----------------------------------+
| 7 | Bob | 3 |
| 5 | Jane | 2 |
| 3 | Joe | 1 |
+-----------------------------------+
Could you please help me getting there. Thanks.
You are looking for a pivot table style query. Here's one way you can do it.
select u.name,
count(case when l.name = 'Lombard' then 1 end) as lombard,
count(case when l.name = 'NYC' then 1 end) as nyc,
count(case when l.name = 'LA' then 1 end) la,
count(u.name) total
from bookings b
inner join events e
on b.event_id = e.event_id
inner join locations l
on e.location_id = l.location_id
inner join users u
on u.user_id = b.person_id
group by u.name
with rollup
fiddle here
It gets a lot harder (and is generally easier to do in the application) if you dont know the possible column (location) values when you are writing the query.
http://sqlfiddle.com/#!9/92d50
SELECT u.name,
SUM(l.name = 'Lombard') lombard,
SUM(l.name = 'NYC') nyc,
SUM(l.name = 'LA') la,
COUNT(*) total
FROM bookings b
LEFT JOIN `events` e
ON b.event_id = e.event_id
LEFT JOIN locations l
ON e.location_id = l.location_id
LEFT JOIN users u
ON u.user_id = b.person_id
GROUP BY u.name
WITH ROLLUP
Related
I'm needing to retrieve shared values from a table based on a value from another table, but don't show duplicates.
Example of what tables I have...
Table - members
+-----------------+
| ID | NAME |
+-----------------+
| 1 | Bob |
| 2 | Jack |
| 3 | Jane |
| 4 | Bruce |
| 5 | Clark |
| 6 | Peter |
+-----------------+
Table - groups
+--------------------------------+
| ID | NAME | MANAGER_ID |
+--------------------------------+
| 1 | Group A | 1 | (Bob)
| 2 | Group B | 2 | (Jack)
| 3 | Group C | 1 | (Bob)
+--------------------------------+
Table - group_members
+--------------------------------+
| ID | GROUP_ID | MEMBER_ID |
+--------------------------------+
| 1 | 1 | 3 | (Group A - Jane)
| 2 | 1 | 4 | (Group A - Bruce)
| 3 | 1 | 5 | (Group A - Clark)
| 4 | 1 | 6 | (Group A - Peter)
| 5 | 2 | 3 | (Group B - Jane)
| 6 | 3 | 4 | (Group B - Bruce)
| 7 | 3 | 5 | (Group C - Clark)
+--------------------------------+
What I am needing
(Note: I'm using * in queries here to shorten code.)
If 'Bob' sees all his groups.
Look at 'group_members' table and show all members that belong to it...
$q = SELECT * FROM groups WHERE manager_id = $id;
$r = mysqli_query($dbc, $q);
while ($row = mysqli_fetch-assoc($r) {
$q2 = SELECT *, count(MEMBERS_ID) AS group_count FROM group_members LEFT JOIN members ON group_members.MEMBER_ID = members.id WHERE group_id = '$row[GROUP_ID]';
$r2 = mysqli_query($dbc, $q2);
while ($row2 = mysqli_fetch-assoc($r2) {
echo $row2['name'];
}
}
This shows me the list as expected.
+------------------------+
| NAME | GROUP COUNT |
+------------------------+
| Jane | 1 |
| Bruce | 1 |
| Clark | 1 |
| Peter | 1 |
| Bruce | 1 |
| Clark | 1 |
+------------------------+
I Add GROUP BY group_members.group_id to my 2nd query and that shows.
+------------------------+
| NAME | GROUP COUNT |
+------------------------+
| Jane | 1 |
| Bruce | 2 |
| Clark | 2 |
| Peter | 1 |
+------------------------+
Which is perfect... But here is the problem
if I add a WHERE members.name LIKE \'%clark%\' then it outputs...
+------------------------+
| NAME | GROUP COUNT |
+------------------------+
| | |
| | |
| Clark | 1 |
| | |
| | |
| Clark | 1 |
+------------------------+
It ignores GROUP BY and shows blank rows where other entries would show.
So with all that said. Does any one know why or a better way to do this please?
Been at it for a while now and would really appreciate any assistance.
EDITED:
Here's the full query with all the columns used:
$q = SELECT * FROM groups WHERE manager_id = $id;
$r = mysqli_query($dbc, $q);
while ($row = mysqli_fetch-assoc($r) {
$q2 = SELECT members.id) AS memid, members.first, members.last, members.comname, members.email, members.sector, (members.status) AS memstatus, (group_members.id) AS groupid, (group_members.member_id) AS memidgroup, group_members.group_id, COUNT(group_members.member_id) AS groupcount, member_roles.role FROM members LEFT JOIN group_members ON members.id = group_members.member_id LEFT JOIN member_roles ON members.role_id = member_roles.id WHERE group_id = '$row[GROUP_ID]' AND members.name LIKE '%clark%' GROUP BY group_members.group_id;
$r2 = mysqli_query($dbc, $q2);
while ($row2 = mysqli_fetch-assoc($r2) {
echo $row2['name'];
}
}
Your query or problem is not completely stated. One cannot guess or assume.
Post your last query as well as all queries dont worry about saving the space.
Those blank rows have data that why they are in the table.
Base on your explanation or your query, here is my simple answer
SELECT id,
(select groups.id from groups where groups.id = group_members.group_id )AS group_members_id,
(select groups.name from groups where groups.id = group_members.group_id )AS group_members_name,
(select members.id from members where members.id = group_members.member_id )AS members_id,
(select members.name from members where members.id = group_members.member_id )AS members_name,
count((select members.id from members where members.id = group_members.member_id ) )as members_id_count FROM group_members WHERE (select members.name from members where members.id = group_members.member_id ) LIKE '%clark%' group by members_id
As you mentioned
WHERE members.name LIKE \'%clark%\'
you were selecting data from the members table whereas you have to select the data from group_members table.
I have used this sql statement in my database that uses COUNT and UNION ALL
SELECT tem.book_id, COUNT( * )
FROM(SELECT book_id FROM borrowdetails
WHERE borrowdetails.borrow_status = 'returned'
UNION ALL
SELECT book_id from reserve) as tem
GROUP BY book_id
ORDER BY book_id DESC
then i used this code to name the id in the PHP table
while($row=mysql_fetch_array($user_query)){
$id=$row['book_id'];
$book_query = mysql_query("select * from book where book_id = '$id'")or die(mysql_error());
}
it works fine but it doesn't unite the data with the same name because it has different id's like this
+------+------+-------+
| id | name | count |
+------+------+-------+
|1 |A | 3 | the id here is not shown at the table in PHP just
+------+------+-------+ inside the database but the A is duplicate.
|2 |A | 1 |
+------+------+-------+
|3 |B | 2 |
+------+------+-------+
my desired output should be like this without the id showing in the table.
+------+-------+
| name | count |
+------+-------+
|A | 4 |
+------+-------+ this is the table that should be shown in PHP
|B | 2 |
+------+-------+
as you could see the name A's count becomes four because i want also to add the COUNT(*) of both A's.
What am i going to do in order to achieve the desired outcome?
btw this is the db tables that are used.
+------+------+ +---------+---------+ +-------+-------+
| book table | |borrowdetails table| | reserve table |
+------+------+ +---------+---------+ +-------+-------+
| id | name | |brw_dt_id| book_id | |res_id |book_id|
+------+------+ +---------+---------+ +-------+-------+
|1 |A | | 1 | 2 | | 1 | 1 |
+------+------+ +---------+---------+ +-------+-------+
|2 |A | | 2 | 3 | | 2 | 1 |
+------+------+ +---------+---------+ +-------+-------+
|3 |B | | 3 | 3 | | 3 | 1 |
+------+------+ +---------+---------+ +-------+-------+
You would want to use book_name rather than using book_id.
I haven't tried this, but it should work
Select book_name, count(*) as cnt from books
where book_id IN (
SELECT book_id FROM borrowdetails
WHERE borrowdetails.borrow_status = 'returned'
UNION ALL
SELECT book_id from reserve
)
GROUP BY Book_Name
ORDER BY Cnt
We would normally write that this way
SELECT book_name
, count(*) cnt
FROM books x
JOIN
( SELECT book_id
FROM borrowdetails
WHERE borrowdetails.borrow_status = 'returned'
UNION ALL
SELECT book_id from reserve
) y
ON y.book_id = x.book_id
GROUP BY Book_Name -- this assumes that book_name is unique
ORDER BY Cnt
My first table structure and data like this (allowance):
-------------------------
|Sno | allwnce |
------------------------|
|1 | HRA |
------------------------|
|2 | CA |
------------------------|
|3 | TA |
------------------------|
|4 | SA |
------------------------
second table structure and data like this (save_employee_allowance):
----------------------------------------------
|Sno | EmpID | allowanceName| amount |
----------------------------------------------|
|1 | EM-1001 | HRA | 1200 |
----------------------------------------------|
|2 | EM-1001 | CA | 800 |
----------------------------------------------|
I want like this :
----------------------------------------------
|Sno | EmpID | allowanceName| amount |
----------------------------------------------|
|1 | EM-1001 | HRA | 1200 |
----------------------------------------------|
|2 | EM-1001 | CA | 800 |
----------------------------------------------|
|3 | EM-1001 | TA | NULL |
----------------------------------------------|
|4 | EM-1001 | SA | NULL |
----------------------------------------------|
I am trying left join like this :
Select *
From save_employee_allowance
LEFT JOIN allowance
ON allowance.allwnce = save_employee_allowance.allowanceName
Where EmpID = 'EM-1001'
But it only give result for matching allowance name
If you want all rows in allowance, then make that the first table in the LEFT JOIN. In addition, you then need to move the WHERE condition to the ON clause:
Select a.Sno, coalesce(em.EmpID, 'EM-1001') as EmpId, a.allowanceName, ea.amount
From allowance a LEFT JOIN
save_employee_allowance ea
ON a.allwnce = ea.allowanceName and ea.EmpID = 'EM-1001';
Hi you have to place allowance on left side beacuse LEFT JOIN keyword returns all rows from the left table (allowance), with the matching rows in the right table (save_employee_allowance). The result is NULL in the right side when there is no match.
select *
From allowance a LEFT JOIN
save_employee_allowance ea
ON a.allwnce = ea.allowanceName where ea.EmpID = 'EM-1001';
I am trying to get some statistics for an online game I maintain. I am searching for an SQL statement to get the result on the bottom.
There are three tables:
A table with teams, each having a unique identifier.
table teams
---------------------
| teamid | teamname |
|--------|----------|
| 1 | team_a |
| 2 | team_x |
---------------------
A table with players, each having a unique identifier and optionally an affiliation to one team by it's unique teamid.
table players
--------------------------------
| playerid | teamid | username |
|----------|--------|----------|
| 1 | 1 | user_a |
| 2 | | user_b |
| 3 | 2 | user_c |
| 4 | 2 | user_d |
| 5 | 1 | user_e |
--------------------------------
Finally a table with events. The event (duration in seconds) is related to one of the players through their playerid.
table events.
-----------------------
| playerid | duration |
|----------|----------|
| 1 | 2 |
| 2 | 5 |
| 3 | 3 |
| 4 | 8 |
| 5 | 12 |
| 3 | 4 |
-----------------------
I am trying to get a result where the durations of all team members is summed up.
result
--------------------------
| teamid | SUM(duration) |
|--------|---------------|
| 1 | 14 | (2+12)
| 2 | 15 | (3+8+4)
--------------------------
I tried several combinations of UNION, WHERE IN, JOIN and GROUP but could not get it right. I am using PostgreSQL and PHP. Can anyone help me?
Just use sum with group by:
select t.teamid, sum(e.duration)
from team t
join players p on t.teamid = p.teamid
join events e on p.playerid = e.playerid
group by t.teamid
If you need all teams to be returned even if they don't have events, then use an outer join instead.
Try this
SELECT teamid, Sum(duration),
AS LineItemAmount, AccountDescription
FROM teams
JOIN teams ON teams.teamid = players.teamid
JOIN events ON players.playersid = events.playersid
JOIN GLAccounts ON InvoiceLineItems.AccountNo = GLAccounts.AccountNo
GROUP BY teamid
http://www.w3computing.com/sqlserver/inner-joins-join-two-tables/
I have 2 tables in MySQL:
Persons
|ID | Name | Address
---------------------------------
| 1 | Someone | Somewhere
| 2 | Person2 | Somewhere else
And the table ActivePages
|ID | PersonID | Page
---------------------------------------
| 1 | 1 | somepage
| 1 | 1 | someotherpage
Now I need a query to return the following:
|PersonID | Count
------------------
|1 | 2
|2 | 0
------------------
Who can help me with this? I think its straight forward but I keep getting wrong values...
Thanks in advance!
SELECT p.ID AS PersonID,
COUNT(a.PersonID) AS `Count`
FROM Persons p
LEFT JOIN ActivePages a ON a.PersonID = p.ID
GROUP BY p.ID
select personid,count(personid) as count from activepages
right join Persons on ActivePages.PersonID = Persons.ID group by personid