Counting and Joins - mysql

I have a query like this:
SELECT c.id, c.name, f.name
FROM companies c
INNER JOIN facilities f ON c.id = f.company
ORDER BY c.name DESC, f.name
I also want to retrieve a COUNT() of all work_orders (a table) that are approved (a column containing 0 or 1) for each row (each facility).
e.g, SELECT COUNT(*) FROM work_orders w WHERE w.facility = f.id AND w.approved = 1
The result should look like
company | facility | count
--------------------------
goog | ohio | 2
goog | cali | 0
tekk | cupertin | 0
As kind of a follow up, i'd also like to add another count column where w.approved = 0

SELECT c.id, c.name, f.name, COUNT(w.id) AS work_orders
FROM companies c
INNER JOIN facilities f ON c.id = f.company
-- LEFT JOIN used in case there are facilities with no work orders
LEFT JOIN work_orders w ON f.id = w.facility AND w.approved = 1
GROUP BY c.id, c.name, f.name
ORDER BY c.name DESC, f.name
To do multiple counts (approved or not):
SELECT c.id, c.name, f.name,
wapp.wo AS approved_work_orders,
wnapp.wo AS non_approved_work_orders,
FROM companies c
INNER JOIN facilities f ON c.id = f.company
LEFT JOIN (SELECT facility, COUNT(*) AS wo FROM work_orders WHERE approved=1 GROUP BY facility) wapp ON f.id = wapp.facility
LEFT JOIN (SELECT facility, COUNT(*) AS wo FROM work_orders WHERE approved=0 GROUP BY facility) wnapp ON f.id = wnapp.facility
ORDER BY c.name DESC, f.name

It looks like you just need a grouping on c.id and an if statement
SELECT c.id, c.name, f.name, IF(count(0)>0,1,0)
FROM companies c
INNER JOIN facilities f ON c.id = f.company
LEFT JOIN work_orders w ON w.facility = f.id
GROUP BY f.id
ORDER BY c.name DESC, f.name

Related

Count two different rows in mysql query

I have organizations. Each organization can have members and projects.
I want to get list of organizations with number of members and projects.
For example,
Organization | Members | Projects | Action
------------------------------------------
Org 1 | 5 | 6 | Delete - Edit
Org 2 | 2 | 9 | Delete - Edit
I am using this query,
SELECT COUNT(m.id) as members, COUNT(p.id) as projects,
o.status,o.organization_name,o.logo, o.id as id
from tbl_organizations o
LEFT JOIN tbl_organization_members m ON (o.id = m.organization_id)
LEFT JOIN tbl_projects p ON (o.id = p.organization_id)
WHERE o.status= 'active' AND o.created_by= 1
But the output of number of projects is equal to number of members.
How can I make the sample above using query?
Try this way:
SELECT o.id as id, o.organization_name, cnt_ as members, cnt_p as projects
from tbl_organizations o
LEFT JOIN (
SELECT organization_id, COUNT(id) cnt_m
FROM tbl_organization_members
GROUP BY organization_id
) m ON (o.id = m.organization_id)
LEFT JOIN (
SELECT organization_id, COUNT(id) cnt_p
FROM tbl_projects
GROUP BY organization_id
) p ON (o.id = p.organization_id)
WHERE o.status= 'active' AND o.created_by= 1
This way you JOIN to an already aggregated version of member/project tables, so as to get the count of members/projects per organization_id.
Group by the organisation columns and count distinct IDs
SELECT o.status,o.organization_name, o.logo, o.id as id,
COUNT(distinct m.id) as members, COUNT(distinct p.id) as projects,
from tbl_organizations o
LEFT JOIN tbl_organization_members m ON (o.id = m.organization_id)
LEFT JOIN tbl_projects p ON (o.id = p.organization_id)
WHERE o.status= 'active'
AND o.created_by= 1
GROUP BY o.status, o.organization_name, o.logo, o.id
You can co-related subquery:
SELECT
o.id as Organization,
(SELECT COUNT(*) FROM tbl_organization_members WHERE organization_id = o.id) as members,
(SELECT COUNT(*) FROM tbl_projects WHERE organization_id = o.id) as projects
FROM
tbl_organizations o
WHERE
o.status= 'active' AND o.created_by = 1

select and count rows

I have 2 tables and I need to select and count rows in one query, maybe somebody can help me with that, my query is:
SELECT
c.id, c.first_name, c.last_name, c.speciality, c.level, c.email, c.skype, c.city,
s.status_type, c.status_id, c.linkedin, c.link_cv, c.interview_res, c.createdAt,
c.updatedAt, c.recruiter_id, u.first_name AS fname, u.last_name AS lname
FROM
Candidates c
JOIN Users u
ON c.recruiter_id = u.id
JOIN Statuses s
ON s.id = c.status_id
WHERE
c.deleted = false
and I need to get count of the rows that respond my select and count them.
example output (what I want):
count | fname | lname | ..... |
---------------------------------
3 | Ihor | Shmidt | ... |
3 | Andre | Agassi | .... |
3 | Roger | Federer| ..... |
i.e. I want to have my fields that I select and their count
Before the "from" portion of the query, please add count (*). It will give you the count of the rows.
Select ......, count (*) from Candidates c
JOIN Users u ON c.recruiter_id = u.id
JOIN Statuses s on s.id = c.status_id
WHERE c.deleted = false;
COUNT(*) as count or COUNT(c.id) as count
SELECT COUNT(*) as count,c.id, c.first_name, c.last_name, c.speciality, c.level, c.email,
c.skype, c.city, s.status_type, c.status_id, c.linkedin, c.link_cv, c.interview_res,
c.createdAt, c.updatedAt, c.recruiter_id, u.first_name AS fname, u.last_name AS lname
FROM Candidates c
JOIN Users u
ON c.recruiter_id = u.id
JOIN Statuses s
ON s.id = c.status_id
WHERE c.deleted = false;
SELECT c.id, ( SELECT COUNT(*) FROM Candidates c
JOIN Users u ON c.recruiter_id = u.id
JOIN Statuses s ON s.id = c.status_id
WHERE c.deleted = false ) AS count FROM Candidates
c JOIN Users u ON c.recruiter_id = u.id
JOIN Statuses s ON s.id = c.status_id
WHERE c.deleted = false ;

inner join 4 tables with group, order by, having clause

I have 4 table and i want to extract: id, nume, localitate, masina_id, nr_inmatriculare, an_fabricatie, rafinarie, marca, and sum (quantity+deliver_quantity) as total_quantity group by an_fabricatie , Order by marca, and put some having clouse.
I don’t know how to make this.
My query is as bellow , but I think isn't correct.
select c.id, c.nume,c.localitate,l.masina_id, i.nr_inmatriculare, i.an_fabricatie,
i.rafinarie, m.marca from clienti c inner join livrari l on c.id = l.id inner join incarcari I on l.incarcare_id = l.livrari_id inner join masina m on i.id_marca = m.id, sum(select quantity, deliver_quantity) as total_quantity group by an_fabricatie having quantity >1000 order by marca;
Incarcari table
Id|livrari_id|id_marca|nr_inmatriculare|an_fabricatie|rafinarie|aviz_incarcare|quantity|
Livrari table
Id|masina_id|client_id|incarcare_id|deliver_quantity|aviz_livrare
Masini table
Id|numar_inmatriculare|marca|an_fabricatie|
Clienti table
Id|nume|localitate|date_add|date_upd|
SELECT c.id, c.nume, c.localitate, l.masina_id, i.nr_inmatriculare, i.an_fabricatie, i.rafinarie, m.marca, (SUM(i.quantity) + SUM(l.deliver_quantity)) AS total_quantity
FROM clienti c
INNER JOIN livrari l ON c.id = l.id
INNER JOIN incarcari i ON l.incarcare_id = i.livrari_id
INNER JOIN masini m ON i.id_marca = m.id
GROUP BY i.an_fabricatie, c.id, c.nume,c.localitate,l.masina_id, i.nr_inmatriculare, i.rafinarie, m.marca
HAVING i.quantity > 1000
ORDER BY m.marca DESC;

MySQL Query get total number of guests per company

select
first_name,
last_name,
c.name as company_name,
sc.`date` as screening_date
from
guests g
inner join
user_guest_group ugs on ugs.guest_id = g.id
inner join
companies c on c.id = g.company_id
inner join
screening_date_guest sdg on sdg.guest_id = g.id
inner join
screening_dates sc on sc.id = sdg.screening_date_id
where
sdg.attending = 1
and
screening_date_id = 1
group by
first_name,
last_name
Results:
Peter, M, Bell Media (ctv), 2015-05-18 00:00:00
Adam, D, Highway Entertainment, 2015-05-18 00:00:00
Todd, F., Multichoice, 2015-05-18 00:00:00
John, D, Talpa, 2015-05-18 00:00:00
Maria, F, UK TV, 2015-05-18 00:00:00
John, L, WBDTD, 2015-05-18 00:00:00
Albert, P, WBDTD, 2015-05-18 00:00:00
My query returns that resulset.
Now, I want to see another column with total guests per company.
In this case, we have 2 guests from WBTDT so it should say total_guest = 2
Can someone help me ?
Thanks
One way to do this is to get the count per company in a correlated subquery, so maybe this is what you want?
select
first_name,
last_name,
c.name as company_name,
sc.date as screening_date,
(
select count(*) from guests
inner join
user_guest_group on user_guest_group.guest_id = guests.id
inner join
companies on companies.id = guests.company_id
inner join
screening_date_guest on screening_date_guest.guest_id = guests.id
inner join
screening_dates on screening_dates.id = screening_date_guest.screening_date_id
where
screening_date_guest.attending = 1
and
screening_date_id = 1 and company_id = c.id
) total_guests
from
guests g
inner join
user_guest_group ugs on ugs.guest_id = g.id
inner join
companies c on c.id = g.company_id
inner join
screening_date_guest sdg on sdg.guest_id = g.id
inner join
screening_dates sc on sc.id = sdg.screening_date_id
where
sdg.attending = 1
and
screening_date_id = 1
group by
first_name,
last_name,
c.id,
c.name,
sc.date
select
first_name,
last_name,
c.name as company_name,
sc.`date` as screening_date,
count(g.id)
from
guests g
inner join
user_guest_group ugs on ugs.guest_id = g.id
inner join
companies c on c.id = g.company_id
inner join
screening_date_guest sdg on sdg.guest_id = g.id
inner join
screening_dates sc on sc.id = sdg.screening_date_id
where
sdg.attending = 1
and
screening_date_id = 1
group by
first_name,
last_name,
c.name

SELECT all rows by WHERE clause

I have the following query which works (without the "WHERE stats.dt" part). I get all users with their data.
My problem is that this query of course results in rows ONLY with users that have stats.dt > $timestampnow-$maxdays_data). But I need ALL users but their values of SUM(upload) or SUM(download) need only to be fetched when stats.dt is larger than tstamp-maxdays. The other rows with values of upload and download where stats.dt is smaller than what I need, can be ignored.
An example would be that the user with nodeid 2 would not be selected because his dt is too small. I do want the user to be selected but just not with data or upload values (they can be 0).
The stats table looks like this
nodeid | dt | upload | download
----------------------------------------
1 | 1381699533 | 345345 | 42324234
1 | 1382899152 | 7575 | 574234
1 | 1380699533 | 764534 | 7235232
2 | 1372899152 | 71455 | 124123
I don't know where to start looking how to solve this so maybe somebody out there can point me in the right direction. Thanks!
SELECT b.id, b.lastname, b.name, c.balance, a.maxdebt, b.warndata, b.warndownload, b.warnupload, b.warndebt, b.cutoffdata, b.cutoffdownload, b.cutoffupload, b.cutoffdebt, b.data, b.download, b.upload, b.warning, b.access, b.cutoffstop
FROM (
SELECT customers.id AS id, SUM(tariffs.value) AS maxdebt
FROM tariffs
LEFT JOIN assignments ON tariffs.id = assignments.tariffid
RIGHT JOIN customers ON assignments.customerid = customers.id
GROUP BY id
) a
JOIN (
SELECT customers.id AS id, UPPER(lastname) AS lastname, customers.name AS name, SUM(stats.upload+stats.download) AS data, SUM(stats.download) AS download, SUM(stats.upload) AS upload, customers.cutoffstop, warndata, warndownload, warnupload, warndebt, cutoffdata, cutoffdownload, cutoffupload, cutoffdebt, nodes.warning, nodes.access
FROM customers
LEFT JOIN nodes ON customers.id = nodes.ownerid
LEFT JOIN stats ON nodes.id = stats.nodeid
LEFT JOIN customerwarnings ON customers.id = customerwarnings.id
WHERE stats.dt > ($timestampnow-$maxdays_data)
GROUP BY id
) b ON a.id = b.id
JOIN (
SELECT customerid, SUM(cash.value) AS balance
FROM cash
GROUP BY customerid
) c ON b.id = c.customerid
Here's a brute force way of doing it. It can almost certainly be simplified, but without knowing more about the table and foreign key structures it's hard to be sure.
What I've done is replace sum(stats.download) with sum(case when stats.dt > ($timestampnow-$maxdays_data) then s.download end) and similarly for upload. I've also changed the join on b to be an outer join:
Select
b.id,
b.lastname,
b.name,
c.balance,
a.maxdebt,
b.warndata,
b.warndownload,
b.warnupload,
b.warndebt,
b.cutoffdata,
b.cutoffdownload,
b.cutoffupload,
b.cutoffdebt,
b.data,
b.download,
b.upload,
b.warning,
b.access,
b.cutoffstop
From (
Select
c.id,
sum(t.value) as maxdebt
From
tariffs t
left join
assignments a
on t.id = a.tariffid
right join
customers
on a.customerid = c.id
Group by
c.id
) a left outer join (
Select
c.id,
upper(lastname) as lastname,
c.name,
sum(s.upload + s.download) as data,
sum(case when stats.dt > ($timestampnow-$maxdays_data) then s.download end) as download,
sum(case when stats.dt > ($timestampnow-$maxdays_data) then s.upload end) as upload,
c.cutoffstop,
warndata,
warndownload,
warnupload,
warndebt,
cutoffdata,
cutoffdownload,
cutoffupload,
cutoffdebt,
n.warning,
n.access
From
customers c
left join
nodes n
on c.id = n.ownerid
left join
stats s
on n.id = s.nodeid
left join
customerwarnings w
on c.id = w.id
Group By
c.id
) b
On a.id = b.id
inner join (
Select
customerid,
sum(cash.value) as balance
From
cash
Group By
customerid
) c
on a.id = c.customerid