How to count all row result as 1 in mysql? - mysql

I have two tables. "tbl_a" which contain fields of patient and hospital, and "tbl_b" which is the consultation.
Now my problem is to only count the patient that has 4 records in "tbl_b" so that if a patient has 4 records in the "tbl_b" then it count as 1.
I want this result only in use of mysql coz and i need this to run in event scheduler.
In short i want to count all patient that has 4 consultation in every hospital. Can anybody help me on this?

Use this solution:
SELECT patient
FROM tbl_b
GROUP BY patient
HAVING COUNT(1) >= 4
Change the >= to = if you just want patients who have exactly four consultations instead of four or more.
Perhaps you want the count of patients who have four or more consultations... in which case you could just wrap the above SELECT and count the number of rows:
SELECT COUNT(1)
FROM
(
SELECT patient
FROM tbl_b
GROUP BY patient
HAVING COUNT(1) >= 4
) a

Assuming tables patients and consultation Joined by patient_id
SELECT * FROM patients
JOIN (SELECT IF(COUNT(patient_id) = 4, patient_id, NULL) AS con
FROM consultation
GROUP BY patient_id) AS con
ON con.patient_id = patients.patient_id
GROUP BY patient_id
the joined table would get only numbers fro consultations which are 4 and all others are NULL hence the join clause in the case would result in records of patients having consultations total 4 only
hope this helps

Try this ::
Select *, count(1)
from table_a a
inner join table_b b
inner join on (a.patient_id=b.patient_id)
group by b.patient_id having count(1) =4

Try this
SELECT
COUNT(consultation )/4 AS Patient_Number
FROM
tbl_b
GROUP BY
consultation
HAVING
(COUNT(consultation ) % 4) = 0

Related

MySQL: get average of value from query

I have 3 table.
Users --> UID, Name, Lat, Longg, Pic
Profile --> pid, uid,City, State, About
Feedback--> fid, uid, ratingby, txnid, rating, feedback_type
Feedback_type can be 1-4 from same txnid. So, if user is giving feedback for all the questions then there will be 4 records for same.
Now i need to show the user details along with the average feedback.
Below is the query i have written so far.
SELECT
a.name,
a.uid,
b.city,
a.pic,
b.state,
b.about
FROM
users AS a
INNER JOIN profile AS b
ON
a.uid = b.uid
I am not sure how can i get the average value from feedback table.
I need show user average feedback and to be more specific. Average of all 4 feedback separately.
Also advise if my approach is good or is there any other best practice that i need to follow.
Edit
I can fetch the single record from feedback.
SELECT uid, avg(rating) FROM `feedback` WHERE uid= 8
But not sure how can i get the average for different feedback_type.
You probably need to create a sub-table to find the average ratings of each type from the Feedbackback table (you can categorize feedback_type for calculating average by using group by f.uid, f.feedback_type). After that, you just need to join the resulting query table with the Users and Profile table to get additional data such as Name, City, etc.
SELECT u1.Name, ar.uid, ar.average_rating, ar.feedback_type, p.City, u1.Pic, p.State, p.About
FROM (
SELECT f.uid, f.feedback_type, AVG(f.rating) AS average_rating
FROM Feedback AS f
WHERE f.uid=8
GROUP BY f.uid, f.feedback_type
) AS ar
INNER JOIN Users AS u1 ON ar.uid=u1.UID
INNER JOIN Profile AS p ON ar.uid=p.uid;
Update: If alias is not working, an alternative approach would be to create a temporary table to calculate user's average rating and use the table to join with Users and Profile tables like above
CREATE TEMPORARY TABLE ar
SELECT uid, feedback_type, AVG(rating) AS average_rating
FROM Feedback
WHERE uid=8
GROUP BY uid, feedback_type;
SELECT Users.Name, ar.uid, ar.average_rating, ar.feedback_type, Profile.City, Users.Pic, Profile.State, Profile.About
FROM ar
INNER JOIN Users ON ar.uid=Users.UID
INNER JOIN Profile ON ar.uid=Profile.uid;
Update: If you need to put the records of 4 feedback types in different columns, you only need to group by uid in ar table and use CASE in AVG to filter out the feedback_type to calculate the average in each column
CREATE TEMPORARY TABLE ar
SELECT
uid,
AVG(CASE WHEN feedback_type = 1 THEN rating END) AS average_rating_1,
AVG(CASE WHEN feedback_type = 2 THEN rating END) AS average_rating_2,
AVG(CASE WHEN feedback_type = 3 THEN rating END) AS average_rating_3,
AVG(CASE WHEN feedback_type = 4 THEN rating END) AS average_rating_4
FROM Feedback
WHERE uid=8
GROUP BY uid;
SELECT
Users.Name,
ar.uid,
ar.average_rating_1,
ar.average_rating_2,
ar.average_rating_3,
ar.average_rating_4,
ar.feedback_type,
Profile.City,
Users.Pic,
Profile.State,
Profile.About
FROM ar
INNER JOIN Users ON ar.uid=Users.UID
INNER JOIN Profile ON ar.uid=Profile.uid;
You can get the avg value using this query SELECT AVG(column_name) FROM table_name WHERE condition;.
To get more columns you should try
SELECT AVG(column_name_1) AS a, AVG(column_name_2) AS b, AVG() AS c, AVG() AS d FROM table_name WHERE condition
I hope i was helpful.

MySQL group and sum with joined tables

I've got pretty tricky problem with MySQL.
I have two tables with one to many relation (below colums that are relevant)
Table A (campaigns):
id | channel_type | date
Table B (budgets):
id | campaign_id | budget
I need single query to fetch following result:
Campaign count by channel_type
Sum of all budgets that are related to found campaigns.
I need to filter results by columns in campaigns table (e.g. WHERE campaigns.date > '2014-05-01')
I have tried following approach:
SELECT channel_type, COUNT(*) cnt,
(SELECT SUM(budget) FROM budgets WHERE budgets.campaign_id = campaigns.id))
as budget
FROM campaigns
WHERE campaigns.date >= 'some-value'
AND [more conditions]
GROUP BY campaigns.channel_type
But this of course fails miserably because of GROUP i am getting only first campaigns.id result for channel_type.
Any tips (and solution) would be really appreciated!
TIA
Get the total budget from budgets table using GROUP BY campain_id. It will be subquery. Name it. For example, A.
Now get the total id counts from campains using GROUP BY channel_type and WHERE date>='some-value'.
Use step 2 and 1(the subquery will act as table) in the final query and you will get the results.
You can post schema and then I can check.
I think this should work :
SELECT channel_type, COUNT(*) cnt,
(SELECT SUM(t2.budget) FROM budgets t2 WHERE t2.campaign_id IN (
SELECT t3.id FROM campaigns t3 WHERE t3.channel_type = t1.channel_type))
AS budget
FROM campaigns t1
WHERE t1.date >= 'some-value'
AND [more conditions]
GROUP BY t1.channel_type
see this fiddle
I've found working solution.
Here's working query:
SELECT SUM(budget) as budget, COUNT(*) as count FROM
(SELECT * FROM campaigns WHERE [conditions]) AS found_campaigns
LEFT JOIN budgets ON budgets.campaign_id = found_campaigns.id
GROUP BY channel_type

JOIN & List Last Records per an ID

There are two tables:
SELECT id,customer FROM records;
SELECT user_id,call_date FROM call_history
Matching columns are:
records.id = call_history.user_id
The call_history table has call logs for customers.
There can be one or more call_history rows per customer.
I need to find when they called last time (for each customer).
For ex. userid=1 called twice, June 16 and July 20. Result must give me July 20, but I need to do the same for all customers from records table.
That is what I tried but it didn't work:
SELECT a.id, FROM_UNIXTIME(b.call_date,'%d/%m/%Y %H:%i') AS lastcall
FROM records a
INNER JOIN call_history b ON a.id=b.user_id
GROUP BY a.id ORDER BY b.call_date DESC;
Thank you.
Does this meet your requirements?
SELECT
r.id,
r.customer,
MAX(ch.call_date) AS lastcall
FROM
records AS r
INNER JOIN
call_history AS ch ON ch.user_id = r.id
GROUP BY
r.id,
r.customer

MySQL join on max value

From joining the tables below on the entry.id, I want to extract the rows from the food_brands table which have the highest type_id - so I should be getting the top 3 rows below, with type_id 11940
food_brands
id brand type_id
15375 cesar 11940
15374 brunos 11940
15373 butchers 11940
15372 bakers 11939
15371 asda 11939
15370 aldi 11939
types
id type quantity food_id
11940 comm 53453 10497
11939 comm 999 10496
foods
id frequency entry_id
10497 twice 12230
10496 twice 12230
10495 once 12230
entries
id number
12230 26
My attempt at the query isn't filtering out the lower type.id records - so from the table records below in food_brands, i'm getting those with type_id 11940 and 11939. Grateful for any help fix this!
SELECT fb.*
FROM food_brands fb
INNER JOIN types t ON fb.type_id = t.id
INNER JOIN
(
SELECT MAX(id) AS MaxID
FROM types
GROUP BY id
) t2 ON t.food_id = t2.food_id AND t.id = t2.MaxID
INNER JOIN foods f ON t.food_id = f.id
INNER JOIN entries e ON f.entry_id = e.id
WHERE entries.id = 12230
A simple subquery should do it just fine;
SELECT * FROM food_brands WHERE type_id=
(SELECT MAX(t.id) tid FROM types t
JOIN foods f ON f.id=t.food_id AND f.entry_id=12230)
An SQLfiddle to test with.
If you just want to return the rows from food_brands with the max type id, you should be able to use:
SELECT fb.*
FROM food_brands fb
INNER JOIN
(
select max(id) id
from types
) t
on fb.type_id = t.id
See SQL Fiddle with Demo
I don't know why you are doing all these inner joins after the one on the t2 subquery, since you are only retrieving the columns of fb, but I suppose that you are not showing the whole query, and you just want to get that one fixed.
The issue is actually in the subquery t2: there, for some untold reason, you choose to do a GROUP BY id which changes the MAX function semantic to generate a maximum value per id, and since you are asking the maximum on that very column, MAX and GROUP BY cancel out each other. Just removing the GROUP BY clause fixes the query.
If for some untold reason you cannot remove that clause, perhaps replacing MAX(id) by id and adding ORDER BY id DESC LIMIT 1 would do.
Also, your subquery should probably select also food_id since it is used in the subsequent INNER JOIN clause.

query to join a table with two fields into one list containing items in both fields

Looking at similar questions, I actually want the exact opposite of this:
SQL query for getting data in two fields from one column
I have a table meetings with paired users:
A_user_id | B_user_id
1 2
3 4
There is a user table as well.
Is there a simple mysql query that lists all the user_ids into one long list?
query result
1
2
3
4
I was thinking something like this but it doesn't work:
select *
from user
where user.id in (
(select A_user_id from meeting)
or
(select B_user_id from meeting)
)
Thanks!
UPDATE (UNION solved this, but let's make this a bit more challenging):
I want to get a list of usernames and location names (both are reference tables) so I need to join this union query to them. Here's what I tried:
select u1.fname, l1.name
from meeting m1
join user u1 on m1.A_user_id=u1.id
join locations l1 on m1.location_id=l1.id
union
select u2.fname, l2.name
from meeting m2
join user u2 on m2.A_user_id=u2.id
join locations l2 on m2.location_id=l2.id
order by location_id asc
I'm getting two errors:
1- Not sure what kind of joins I need on these. (without the last 'order by' line) I'm getting a list of only 2 (there should be 4, as there are 2 pairs of people meeting). It seems to be pulling only the first item from each part of the union. I believe this relates to the type of join I'm doing for each, but not sure. So, users are distinct (there is only 1 user in the meeting table and it matches only 1 user in the user table), but locations are not (2 users are meeting at 1 location, and I think when I join on locations it is messing things up).
2- How do I use the "order by" at the end to order by the resulting list of "location_id"s, since now I have two named tables to deal with.
Thanks!
UPDATE 2:
Ok I put the two selects into parenthesis and UNIONed them and now I can order by the location_id... but I still have no idea how to join on the location table. Mysql doesn't like what I tried
(select u1.fname, m1.location_id
from meeting m1
join user u1 on m1.A_user_id=u1.id)
union
(select u2.fname, m2.location_id
from meeting m2
join user u2 on m2.B_user_id=u2.id)
#join locations l on l.id = location_id // this line messes things up *
order by location_id asc
Doesn't there need to be an all encompassing select around this whole thing?
How do I join the locations.id field on the "location_id" field that gets kicked off of the union query? Since the "location_id" field is technically in two different tables?
THe join above throws an error.
UPDATE 3: SOLVED
Here's my final query:
select tb1.fname, l.name
from (
(select u1.fname, m1.location_id
from meeting m1
join user u1 on m1.A_user_id=u1.id)
union
(select u2.fname, m2.location_id
from meeting m2
join user u2 on m2.B_user_id=u2.id)
) tb1
join locations l on l.id = tb1.location_id
order by location_id asc
select A_user_id as id from meetings
union
select B_user_id as id from meetings
in your example code, you could use an 'or', but the 'or' has to join two 'in' statements, if you get what I mean.
select *
from user
where
(
(user.id in (select A_user_id from meeting))
or
(user.id in ((select B_user_id from meeting))
)
And to answer you second update, you want something like
select locations.* from
(
(select A_user_id as id from meeting)
union
(select B_user_id as id from meeting)
) as UIDS
join
locations on locations.id = UIDS.id
select A_user_id as user_id from meetings
union all
select B_user_id as user_idfrom meetings
order by user_id
Notes:
UNION ALL keeps duplicates, UNION doesn't
Any ORDER BY goes at the end of the UNION