trying to add if condition to do the following
1- selecting data depending on if that data selected before by the user
2- selecting data depending on how many time that data was selected by all users
3- setting maximum number of how many times the data could be selected by all user
here is my current code as you can see all that i made the first condition and it work fine
$sql=mysql_query(
"SELECT courseid,coursename
FROM newcourses
where (courseid not in (select courseid from applicants)
)"
);
for example :
if i have table newcourses that have these rows
courseid coursename max applicant
1 English standard 3
2 English advance 2
3 Spanish 4
and table applicants have these rows
id name courseid
1 me 1
2 jon 1
3 jake 2
4 sara 2
5 joe 3
so how to do so
Try something like this:
SELECT n.courseid, n.coursename
FROM newcourses n
LEFT JOIN applicants a ON n.courseid = a.courseid
GROUP BY n.courseid, n.coursename
HAVING count(a.id) <=1;
This will get all the courses that don't have any applicants and the ones that have one applicant.
And it doesn't use a subquery that has to run once for every record selected, so you gain on performance also.
This uses a LEFT JOIN between newcourses and applicants tables. This shows any element of newcourses that have records in applicants table but shows also the ones that aren't in the applicants table (that's the reason to use LEFT JOIN).
sqlfiddle demo
If you want to check them separately you can do:
To get the courses with no applicants:
SELECT n.courseid, n.coursename
FROM newcourses n
LEFT JOIN applicants a ON n.courseid = a.courseid
GROUP BY n.courseid, n.coursename
HAVING count(a.id) = 0;
To exclude courses with two applicants:
SELECT n.courseid, n.coursename
FROM newcourses n
LEFT JOIN applicants a ON n.courseid = a.courseid
GROUP BY n.courseid, n.coursename
HAVING count(a.id) != 2;
If you can't have more than two, you can change the != to <
If you end up adding a new column to newcourses with the max number of applicants, you can't put that in an external HAVING COUNT, so you would have to do a subquery:
SELECT n.courseid, n.coursename
FROM newcourses n
LEFT JOIN applicants a ON n.courseid = a.courseid
WHERE n.maxApplicants >= (SELECT count(*)
FROM applicants ap WHERE ap.courseid = n.courseid)
GROUP BY n.courseid, n.coursename
Is this what you want to do ?
$sql = mysql_query(
"SELECT courseid,coursename
FROM newcourses
WHERE (courseid NOT IN (SELECT courseid FROM applicants GROUP BY courseid HAVING( COUNT( courseid ) > 1)))
"
);
"HAVING (COUNT (courseid) > 1))" will return multiples ocurences values of the table "applicants".
You must include all negative rows on subquery by using filter like GROUP BY - HAVING.
SELECT courseid, coursename
FROM newcourses
WHERE courseid NOT IN (SELECT courseid FROM applicants GROUP BY courseid HAVING COUNT(courseid) > 1)
Easier to read:
SELECT courseid, coursename
FROM newcourses
WHERE courseid IN (SELECT courseid FROM applicants GROUP BY courseid HAVING COUNT(courseid) = 1)
SELECT courseid,coursename
FROM newcourses
where courseid not in (select courseid from applicants GROUP BY courseid HAVING COUNT(courseid)=2)
If you want to ignore courseids which are triplets or more use HAVING COUNT(courseid)>1
Related
In first table album has id and second table album_details has sub_id which relates from album table id
I need to display count for separate id value.
SELECT DISTINCT B.SUB_ID, A . * , B.CONTENT_VALUE AS detail,
(SELECT COUNT( ID )
FROM album_details WHERE A.ID = B.SUB_ID ) AS count
FROM album AS A, album_details AS B
WHERE A.WEBSITE_ID = '571710720'
AND A.ID = B.SUB_ID
GROUP BY B.SUB_ID
LIMIT 0 , 30
Now count column shows 40 for all rows but need to display 'count' 6 for 'id=4', 'count' 3 for 'id=2'
SELECT count(SUB_ID),SUB_ID from album_details group by SUB_ID
GROUP BY is your weapon of choice.
SELECT
a.ID,
a.CONTENT_VALUE,
COUNT(ad.ID)
FROM albums AS a
LEFT JOIN album_details AS ad ON a.ID = ad.SUB_ID
GROUP BY a.ID
Feel free to add your WHERE before the GROUP BY.
Lets say first table is A and second table is B then query will be like this
select a.ID, count(b.SUB_ID) AS total
FROM A LEFT JOIN B ON A.ID = B.SUB_ID
Group by B.SUB_ID.
It might help you. If not then ask please.
select count(sub_id) as count1 from album_details where sub_id in(select id from album) WHERE album.WEBSITE_ID = '571710720'
AND album.ID = album_details.SUB_ID
I have 4 tables called shops, users, review and rating.
I want to get all reviews for the corresponding shop with reviewed user details and also overall rating for that shop.
I have done almost with the single query. But the problem is if the shop has same rating for multiple times by same user its consider as single rating. But that rating count was correct.
i.e
from this table user_id 3 was rated shop_id 1 as 4 times. So the count is 4 and total_rating is 17.
My query is
select review.comments, users.username, count(distinct rating.id) as rating_count,
sum(distinct rating.rating) as total_rating from users
left join review on users.id = review.user_id and review.shop_id='1'
left join rating on users.id = rating.user_id and rating.shop_id='1'
where review.shop_id='1' or rating.shop_id='1'
group by users.id, review.user_id, rating.user_id, review.id
When I run this query I got
But I need total_rating 17 for user_id 3..
Check this fiddle
You put DISTINCT IN sum( rating.rating) as total_rating, thats why the result(12=17-5), since it will include 5 only once while computing sum.
select review.comments, review.user_id, count(distinct rating.id) as rating_count,
sum( rating.rating) as total_rating from users
left join review on users.id = review.user_id and review.shop_id='1'
left join rating on users.id = rating.user_id and rating.shop_id='1'
where review.shop_id='1' or rating.shop_id='1'
group by users.id, review.user_id, rating.user_id, review.id
Here is SQLFiddle
Sample Output :
Hope this helps
Try this - Remove the distinct from sum(rating.rating). Since you gave sum(distinct rating.rating), it is ignoring one 5 that user 3 gave to store 1.
select review.comments, users.username, count(distinct rating.id) as rating_count,
sum(rating.rating) as total_rating from users
left join review on users.id = review.user_id and review.shop_id='1'
left join rating on users.id = rating.user_id and rating.shop_id='1'
where review.shop_id='1' or rating.shop_id='1'
group by users.id, review.user_id, rating.user_id, review.id
First of all: It makes no sense to outer-join records from a table and then remove them in the WHERE clause. With left join review ... you say: find a matching record in table review, and if you don't find any, then add nulls, so we keep the users record. Then with where review.shop_id='1' you say: keep only records where you actually found a record in review. So you are dismissing the records that you just took the pain to keep. Your WHERE clause renders your LEFT OUTER JOINS mere INNER JOINS.
As to your actual problem: That stems from joining all tables first and only then trying to get aggregates from the resulting records. Aggregate before joining instead:
select
rev.comments,
usr.username,
coalesce(rat.rating_count, 0) as rating_count,
rat.total_rating
from review rev
join users usr on users.id = review.user_id
left join
(
select user_id, shop_id, count(*) as rating_count, sum(rating) as total_rating
from rating
group by user_id, shop_id
) rat on rat.user_id = usr.id and rat.shop_id = rev.shop_id
where rev.shop_id = 1
group by rev.id;
Suppose I have a table named studens.
I want to count how many students who received duplicated scores at least 2 times.
Please help me, thanks.
The result that I expect is: Jonh have 100 score 2 times, James have 80 scores 2 times, Julia has 50 scores 2 times. So the amount of students who receive duplicated score at least 2 times is 3 (Jonh, Jam, and Julia).
select count(*) from
(
select name
from your_table
group by name, score
having count(*) > 1
) x
Based on the edit, your query would be:
select distinct name
from students
group by name, score
having count(*) > 1;
You could see the scores and counts by doing:
select name, score, count(*)
from students
group by name, score
having count(*) > 1;
By the way, the first query is one of the very, very few times where select distinct is appropriate with a group by. I think the second query provides more information, though.
Assuming a student has only one score per subject (that is, name, subject is unique):
SELECT COUNT(DISTINCT t1.name)
FROM scores t1
INNER JOIN scores t2
ON t1.name = t2.name
AND t1.subject <> t2.subject
AND t1.score = t2.score
SQLFiddle
I have two tables,
TABLE 1 has many of each client and campaign and is very large
TABLE 2 has only one of each client and campaign and is small.
So I want to get the lastest(highest ID) from TABLE 1 where it matches the client and campaign in TABLE 2 and only one of each.
I have tried MAX, and playing with the order by etc, but cant get it working....
The results I get are choosing the lowest ID from TABLE 1 (I want highest)
$result2 = mysql_query("SELECT table1.client,table1.campaign,table1.id
FROM table1
LEFT OUTER JOIN
table2
ON (table2.client = table1.client)
AND (table2.campaign = table1.campaign )
WHERE (table2.enabled != 'disabled')
group by campaign asc
order by client,campaign,id asc
");
Help needed....
SELECT * FROM table1
INNER JOIN
(
SELECT MAX(table1.id) AS id FROM table1
INNER JOIN table2 ON table2.client = table1.client AND table2.campaign=table1.campaign and table2.enabled != 'disabled'
GROUP BY table1.client, table1.campaign
) AS m ON m.id = table1.id
I think that's what you're asking for. For each combination of client and campaign that exists in each table, it will give you the highest ID in table 1.
table user:
id_u* f_name l_name
----------------------
1 andi mitchel
2 sarah bench
3 kirsty larx
table voucher:
id_v* id_user id_target
1 1 2
2 2 3
quite confused how to join those table with two foreign keys
$db->query("SELECT * FROM voucher v
LEFT JOIN user u ON u.id_u = v.id_user
LEFT JOIN user u1 ON u1.id_u = v.id_target
WHERE .... ")
echoing while loop... and returns nothing??
while($r = $q->fetch_array(MYSQLI_ASSOC)) :
echo $r['u.f_name'];
echo $r['u1.f_name'];
endwhile;
Your JOIN seems absolutely correct. The only issue is that you have joined table user twice, therefore you have columns with same name (like f_name). The database will assign different (but arbitrary) names to these columns. You can override this behaviour with the AS keyword:
$db->query("SELECT v.*
, u.f_name AS user_f_name
, u.l_name AS user_l_name
, ta.f_name AS target_f_name
, ta.l_name AS target_l_name
FROM voucher v
LEFT JOIN user u ON u.id_u = v.id_user
LEFT JOIN user ta ON ta.id_u = v.id_target
WHERE .... ")
Then:
while($r = $q->fetch_array(MYSQLI_ASSOC)) :
echo $r['user_f_name'];
echo $r['target_f_name'];
endwhile;
And I think you can replace the LEFT JOINs with (inner) JOINs. Unless you have id_user or id_target values referencing non-existing userids (id_u).
It looks like you are asking for all people who are in the voucher table regardless of them being in position 1 (user) or position 2 (target)... Then, showing that person's name.
This query does a pre-query of each possible person and their position basis (via WhichPosition).
SELECT STRAIGHT_JOIN
AllVoucherUsers.WhatPosition,
u.*
FROM
( select distinct
v.id_user,
'1' as WhatPosition
from voucher v
union select distinct
v.id_target as id_user,
'2' as WhatPosition
from voucher v
) AllVoucherUsers
join users u
on AllVoucherUsres.id_user = u.id_u
If you only want ONE instance of a given person -- REGARDLESS of their position, just strip out all instances of the "WhatPosition" reference...
SELECT STRAIGHT_JOIN
u.*
FROM
( select distinct
v.id_user
from voucher v
union select distinct
v.id_target as id_user
from voucher v
) AllVoucherUsers
join users u
on AllVoucherUsres.id_user = u.id_u
SELECT * FROM voucher v
LEFT JOIN user u ON u.id_u = v.id_user OR u.id_u = v.id_target
WHERE ....
how about:
SELECT * FROM voucher JOIN user ON id_user = id_u
Simpler still:
SELECT * FROM voucher, user WHERE id_user = id_u