where using alias of aggregate - mysql

This query
select r1.name, count(stars) as reviewCount
from (reviewer r1 join reviewer r2 using(rID)) join rating using(rID)
group by r1.name;
Yields the following output
+------------------+--------------+
| name | reviewCount |
+------------------+--------------+
| Ashley White | 1 |
| Brittany Harris | 3 |
| Chris Jackson | 3 |
| Daniel Lewis | 1 |
| Elizabeth Thomas | 2 |
| James Cameron | 1 |
| Mike Anderson | 1 |
| Sarah Martinez | 2 |
+------------------+--------------+
i want to list users who have reviewCount > 3, something like below
+------------------+--------------+
| name | reviewCount |
+------------------+--------------+
| Brittany Harris | 3 |
| Chris Jackson | 3 |
+------------------+--------------+
i have tried using where and having clause but they result in Empty set (0.01 sec)
select r1.name, count(stars) as reviewCount
from (reviewer r1 join reviewer r2 using(rID)) join rating using(rID)
group by r1.name
having reviewCount > 3;
What is it that i am missing?
edit1 : refer this for sample data to test
edit 2: Also can anyone suggest how can i write this query without using count and having

The result is actually correct but your query needs a little modification. You need to use >= rather than >
HAVING reviewCount >= 3;
I'd rather use the aggregated column than it's alias since it will work on most RDBMS.
HAVING count(stars) >= 3

Related

Count row on table2 based on table1 with prepared statement

I have 2 tables:
clients_db
| clnt_id | clnt_sid | usr_sid | clnt_name |
| 1 | 12345678 | 10001 | Peter |
| 2 | 87654321 | 10001 | Mikey |
aircon_client_db
| ac_id | clnt_sid |
| 1 | 12345678 |
| 2 | 12345678 |
| 3 | 12345678 |
| 4 | 87654321 |
| 5 | 87654321 |
This is query:
select *,count(air.ac_id) as nAC
from clients_db clnt
left join aircon_client_db air on air.clnt_sid=clnt.clnt_sid
where clnt.usr_sid=?
group by clnt.clnt_sid
order by clnt.clnt_name asc
From the code above. I expect the result clnt_id[1]=3 and clnt_id[2]=2. But the result returns 0 for all. Where should I fix?
You just need to select the count(air.ac_id).
Also replace clnt.usr_sid=? with clnt.clnt_id=? if you're going to expect a result like clnt_id[1]=3.
select count(air.ac_id) as nAC
from clients_db clnt
left join aircon_client_db air on air.clnt_sid=clnt.clnt_sid
where clnt.clnt_id=?
group by clnt.clnt_sid
order by clnt.clnt_name asc
Are you missing clnt_name as column in your question?
Don't use * but explicit column name or in this case you could also use clnt.* (you don't need the value for the left joined table but only the count(*)
select clnt.clnt_id, clnt.clnt_sid ,count(air.ac_id) as nAC
from clients_db clnt
left join aircon_client_db air on trim(air.clnt_sid)=trim(clnt.clnt_sid)
AND trim(clnt.user_sid)= '10001'
group by clnt.clnt_sid
order by clnt.clnt_name asc

How to count unique items in column in Access

I need help. I can't seem to find the logic behind this code.
I am working on a voting system, and I need to output the results of the votes.
I want to count all of the rows that has a unique name in it and output how many.
My table goes like this.
voterid | pres | vpres | sec | trea | PIO
---------------------------------------------
1 | John | Mitch | James | Jack | Eman
2 | John | Pao | Bryan | Jack | Faye
3 | Kelvin | Pao | James | Jeck | Faye
Output should be
Pres | Votes
--------------
John | 2
Kelvin | 1
Here's my code.
SELECT DISTINCT
pres,
(SELECT COUNT(pres) FROM (SELECT DISTINCT pres FROM tblVote AS Votes)) AS Votes
FROM tblVote
Thanks in advance!
I think you are just looking for a simple GROUP BY query:
SELECT pres, COUNT(*) AS Votes
FROM tblVote
GROUP BY pres

Mysql count per distinct user with a join

currently i have two tables with some data. the first table has the following:
+----------------+-----------+
| name | member_id |
+----------------+-----------+
| Juice Box | 49432 |
| Rainsurge | 49631 |
| spiderpigrider | 50482 |
+----------------+-----------+
The second table has the following:
+------------+-----------+
| recruit_id | bin(refs) |
+------------+-----------+
| 49432 | 1 |
| 49631 | 1 |
| 49432 | 1 |
| 49631 | 1 |
| 49432 | 1 |
| 49631 | 1 |
| 49432 | 1 |
| 49631 | 1 |
| 49432 | 1 |
| 49631 | 1 |
+------------+-----------+
I would like to return the name, total refs and member_id/recruit_id like so (listing only users with at least 1 ref)
+------------+-----------+------------+
| recruit_id | name | total_refs |
+------------+-----------+------------+
| 49631 | Rainsurge | 5 |
| 49432 | Juice Box | 5 |
+------------+-----------+------------+
select r.recruit_id,bin(r.refs),ipb.name from refs as r
inner join syndicate_ipb.core_members as ipb on ipb.member_id=r.recruit_id;
this returned my data but obviously without a total count and repeated names/ids
select r.recruit_id,count(bin(r.refs)),ipb.name from refs as r
inner join syndicate_ipb.core_members as ipb on ipb.member_id=r.recruit_id;
this returned data with the total count of everyone but only one id/name
+------------+--------------------+-----------+
| recruit_id | count(bin(r.refs)) | name |
+------------+--------------------+-----------+
| 49432 | 10 | Juice Box |
+------------+--------------------+-----------+
this returns the data but again without a count
select distinct r.recruit_id,bin(r.refs),ipb.name from refs as r
inner join syndicate_ipb.core_members as ipb on ipb.member_id=r.recruit_id;
+------------+-------------+-----------+
| recruit_id | bin(r.refs) | name |
+------------+-------------+-----------+
| 49432 | 1 | Juice Box |
| 49631 | 1 | Rainsurge |
+------------+-------------+-----------+
Any help or guidance is greatly appreciated. I feel like i'm close here but just not competent enough with SQL to get it. thanks!
You were almost there. You just missed the GROUP BY clause at the end.
Query:
SELECT
r.recruit_id,
count(bin(r.refs)),
ipb.name
FROM refs AS r
INNER JOIN syndicate_ipb.core_members AS ipb
ON ipb.member_id = r.recruit_id
GROUP BY r.recruit_id;
Note:
If bin(refs) column always contains value 1 then actually you don't need to keep that column. In that case you can use count(*) or count(r.recruit_id) to get the count.
And if bin(refs) column contains any value then count will not give you the right answer. In that case you need to use sum like Sum( bin(refs)).
You have to use the group by clause:
select r.recruit_id, ipb.name, count(bin(refs)) as total_refs
from refs as r
inner join syndicate_ipb.core_members as ipb
on ipb.member_id=r.recruit_id
group by r.recruit_id, ipb.name
having count(bin(refs)) >= 1
This group by r.recruit_id, ipb.name will group the results and this having count(bin(refs)) >= 1 will garante that it only returns members with at least one ref
Do not only group your columns just by the ones you want. Even though MySql allows it, it is not SQL Ansi pattern and even MySql now is complying with it. Use an aggregation function grouping with your entire columns on the select statement.
SELECT ipb.*, COUNT(`r`.`recruit_id`) AS cid FROM `ipb`
INNER JOIN `r` ON `r`.`join_id` = ipb.`member_id`
GROUP BY ipb.`member_id`

My sql listing entries which are repeated more than certain value

I have a staff table like this --->
+------+------------------+------+------------+--------+
| EC | Name | Code | Dob | Salary |
+------+------------------+------+------------+--------+
| 2001 | ROBBIE KEANE | VSS1 | 1990-05-16 | 18000 |
| 2002 | ANSUMAN BANERJEE | VSS1 | 1985-05-21 | 18000 |
| 2003 | OMAR GONZALEZ | SACP | 1989-04-16 | 20000 |
| 2004 | ALAN GORDON | IALO | 1989-05-03 | 20000 |
| 2005 | ROBBIE KEANE | IALO | 1988-01-16 | 18000 |
| 2006 | CHANDLER HOFFMAN | BBDP | 1988-07-17 | 22000 |
| 2007 | PAUL POGBA | BHSM | 1990-08-16 | 18000 |
| 2008 | SHINJI KAGAWA | LPDC | 1991-01-20 | 18000 |
+------+------------------+------+------------+--------+
And now i want to list those codes (like VSS1), which have less than specified number of people assigned with them(say like less than 2) , how can i do this please help.
My query up till now is-->
SELECT Code,count(*) as 'Number of Staff' from STAFF where Code IN (SELECT Code from STAFF GROUP BY CODE LIMIT 2);
But this is not working.
You can filter row count for each Code group with the HAVING clause :
SELECT Code
, COUNT(*)
FROM STAFF
GROUP BY Code
HAVING COUNT(*) < 2
If you need to know the names of the people having this count less than 2 then...
SELECT S.EC, S.Name, S.Code, S.DOB, S.Salary, SC.Code, SC.Cnt
FROM STAFF S
INNER JOIN (SELECT Count(*) cnt, Code FROM STAFF GROUP BY CODE) SC
on S.Code = SC.code
WHERE SC.CNT < 2
should work in SQL server and mySQL. Though SQL Sever could also use a windowed set which would be faster.
If however, you just need to know the Codes having less than a certain number, notulysses having clause should fit the bill.

Need help writing a SQL statement

I need help writing a SQL statement that will create a SQL view from two different tables that will capture 2 records from each possibility.
For example, if there are three records in the customer table that match GROUP A and STATE of NV, you should only show 2 of the 3 records in the view-but if a customer is in GROUP A and STATE of PA or GROUP B and STATE of NV, those additional records will also need to be captured in the view.
I am new to SQL. None of my ideas have worked, so I appreciate any feedback that will help me solve the problem. The following query is what I managed to write:
SELECT customer_table.Customer_ID,
customer_table.First_Name,
customer_table.Last_Name,
customer_table.Email_Address,
customer_table.STATE,
customer_table.GROUP_,
customer_table.Timestamp_,
product_table.Prod_Name,
product_table.Prod_desc
FROM customer_table
INNER JOIN product_table ON customer_table.Customer_ID = product_table.Customer_ID
ORDER BY customer_table.STATE,
customer_table.GROUP_;
And here is the view that it generates:
+-------------+------------+-----------+--------------------+-------+--------+---------------------+----------------+----------------+
| Customer_ID | First_Name | Last_Name | Email_Address | State | GROUP_ | Timestamp_ | Prod_Name | Prod_desc |
+-------------+------------+-----------+--------------------+-------+--------+---------------------+----------------+----------------+
| 4 | Leon | Durham | ldurham#cubs.com | CA | A | 2016-01-25 03:04:22 | Baseball glove | Rawlings glove |
| 1 | Bob | Dernier | bdernier#cubs.com | IL | A | 2016-01-25 02:58:45 | Baseball glove | Rawlings glove |
| 2 | Ryan | Sandberg | rsandberg#cubs.com | IL | A | 2016-01-25 03:02:27 | Baseball glove | Rawlings glove |
| 1 | Bob | Dernier | bdernier#cubs.com | IL | A | 2016-01-25 02:58:45 | Jersey | Chicago jersey |
| 5 | Kieth | Moreland | kmoreland#cubs.com | IL | A | 2016-01-25 03:05:52 | Baseball glove | Rawlings glove |
| 1 | Bob | Dernier | bdernier#cubs.com | IL | A | 2016-01-25 02:58:45 | Hat | Cubs hat |
| 7 | Ron | Cey | rcey#cubs.com | YN | B | 2016-01-25 03:07:53 | Baseball glove | Rawlings glove |
| 6 | Jody | Davis | jdavis#cubs.com | YN | B | 2016-01-25 03:07:08 | Baseball glove | Rawlings glove |
+-------------+------------+-----------+--------------------+-------+--------+---------------------+----------------+----------------+
I believe your best bet is a UNION query. This will stack the results of two seperate SELECT statements on top of each other. Furthermore, you can filter the two queries using a WHERE clause. The second one will be a bit trickier since you have two conditions, so we'll use an OR to seperate them.
/* First SELECT finds two records in Nevada for Group A*/
SELECT TOP 2
customer_table.Customer_ID,
customer_table.First_Name,
customer_table.Last_Name,
customer_table.Email_Address,
customer_table.STATE,
customer_table.GROUP_,
customer_table.Timestamp_,
product_table.Prod_Name,
product_table.Prod_desc
FROM customer_table
INNER JOIN product_table ON customer_table.Customer_ID = product_table.Customer_ID
WHERE customer_Table.GROUP_ = 'A' AND customer_table.STATE = 'NV'
/*UNION ALL will stack the results of these two queries into a single result set*/
UNION ALL
/*Second SELECT finds all records for PA, GROUP A and NV, GROUP B*/
SELECT
customer_table.Customer_ID,
customer_table.First_Name,
customer_table.Last_Name,
customer_table.Email_Address,
customer_table.STATE,
customer_table.GROUP_,
customer_table.Timestamp_,
product_table.Prod_Name,
product_table.Prod_desc
FROM customer_table
INNER JOIN product_table ON customer_table.Customer_ID = product_table.Customer_ID
WHERE (customer_table.GROUP_ = 'A' AND customer_Table.STATE = 'PA') OR
(customer_table.GROUP_ = 'B' AND customer_table.STATE = 'NV')
Lastly, that TOP 2 is SQL Server syntax to say "Return only the top two records for this result set" if this is MYSQL then take out the TOP 2 and stick LIMIT 2 at the end of that SELECT statement instead.