Select something from mysql database and order it by count (where) - mysql

I have a problem with selecting something from my database. Here is the sql sentence:
SELECT name
FROM table1
JOIN table2
ON table1.id=table2.advid
GROUP BY advid
ORDER BY COUNT(table2.likes) ASC
This will output name with the least table2.likes to the highest value of table2.likes
The problem is that table2.likes contain both likes and dislikes. Likes are marked with 1, and dislikes are marked with 2 in the table.
Currently, if there is...
...written in the table, the syntax will count both likes and dislikes so the result would be 6. I would need this result to be zero, which means when counting, dislikes have to be deduced from the number of likes. Which also means this part of the sentence: ORDER BY COUNT(table2.likes) ASC would have to be changed, but I don't know how.

Use conditional aggregation with SUM():
SELECT name
FROM table1 t1 JOIN
table2 t2
ON t2.id = t2.advid
GROUP BY name
ORDER BY SUM(CASE WHEN t2.likes = 1 THEN 1 ELSE -1 END) ASC;
Note: I changed the GROUP BY to be by name. The GROUP BY columns should match the columns you are selecting.

Use a case expression to count 1 for likes and -1 for dislikes. It is considered good style and less error-prone not to join and then aggregate, but to join the already aggregated data instead.
select t1.name, t2.sumlikes
from table1 t1
join
(
select advid, sum(case when likes = 1 then 1 else -1 end) as sumlikes
from table2
group by advid
) t2 on t2.advid = t1.id
order by sumlikes;
If you want to list names without like entries, too, then turn the join into a left outer join and select coalesce(t2.sumlikes, 0) instead.

Related

why the sql correct and the inner mechanism for run it?

the sql as follows come from mysql document. it is:
SELECT * FROM t1 AS t
WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
The document say It finds all rows in table t1 containing a value that occurs twice in a given column , and doesnot explain the sql.
t1 and t is the same table, so the
count(*) in subquery == select count(*) from t
, isn't it?
count(*) in subquery == select count(*) from t
is wrong. because in mysql you can't use it like that. so you have to run it like that to get result of same id having two rows.
if you want to get count of same occurrence,
SELECT id, name, count(*) AS all_count FROM t1 GROUP BY id HAVING all_count > 1 ORDER BY all_count DESC
And also you can get values as your query like this as well,
select * from t1 where id in ( select id from t1 group by id having count(*) > 1 )
The query contains a correlated subquery in WHERE clause:
SELECT COUNT(*) FROM t1 WHERE t1.id = t.id
It is called correlated because it is related to the main query via t.id. So, this subquery counts the number of records having an id value that is equal to the current id value of the record returned by the main query.
Thus, predicate
(SELECT COUNT(*) FROM t1 WHERE t1.id = t.id) = 2
evaluates to true for any row with an id value that occurs twice in the table.
SELECT * FROM t1 AS t
WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
This query goes through each record in t1 and then in the subquery looks into t1 again to see if in this case id is found 2 times (and only 2 times). You can do the same for any other column in t1 (or any table for that matter).
When you would like to see all values that are multiple times in the table, change WHERE 2 = by WHERE 1 <. This will also give you the values that are 3 times, 4 times, etc. in the table.
{
SELECT id,count( * )
FROM
MyTable
group by id
having count( * )>1
}
with this code, you can see the rows which repet more than one,
and you can change this query by yourself
How about using GROUP BY and HAVING:
SELECT id, count(1) as Total FROM MyTable AS t1
GROUP BY t1.id
HAVING Total = 2

COUNT(*) returning number of rows before GROUP BY clause?

I have the follwing query:
SELECT COUNT(*)
FROM mydb.table1 t1
JOIN mydb.table2 t2 ON t1.id = t2.t1_id
WHERE t1.user_id = 44 AND t1.date_deleted IS NULL
GROUP BY t2.system_id, CASE WHEN t2.system_id IS NULL THEN t2.id ELSE 0 END
It returns COUNT(*) = 6, when it should be returning 1 since all six rows for this user have the same t2.system_id (so they should be grouped).
If I change the query to select * instead of COUNT(*), it only returns a single row. If I then remove the GROUP BY clause, six rows are returned.
This makes me think COUNT(*) is returning the row count before the GROUP BY clause is executed, but from what I've read that's not how it's supposed to work.
Is this behavior normal?
Try this:
select count(*) from (
SELECT *
FROM mydb.table1 t1
JOIN mydb.table2 t2 ON t1.id = t2.t1_id
WHERE t1.user_id = 44
AND t1.date_deleted IS NULL
GROUP BY t2.system_id,
CASE WHEN t2.system_id IS NULL THEN t2.id ELSE 0 END
) q1
count gives you the number of (not null) items in each group, so yes, it is definitely working the way it is intended. This means that if you just want the total number of groups, the easiest way is to just wrap it in another query.
It returns the count of items in each group. You have one group with six items in it, so it returns one row containing a column valued 6.

SELECT with a COUNT of another SELECT

I have a table in SQL that is a list of users checking in to a website. It looks much like this:
id | date | status
------------------
Status can be 0 for not checking in, 1 for checked in, 2 for covered, and 3 for absent.
I'm trying to build one single query that lists all rows with status = 0, but also has a COUNT on how many rows have status = 3 on each particular id.
Is this possible?
MySQL VERSION
just join a count that is joined by id.
SELECT t.*, COALESCE(t1.status_3_count, 0) as status_3_count
FROM yourtable t
LEFT JOIN
( SELECT id, SUM(status=3) as status_3_count
FROM yourtable
GROUP BY id
) t1 ON t1.id = t.id
WHERE t.status = 0
note: this is doing the boolean sum (aka count)..
the expression returns either true or false a 1 or a 0. so I sum those up to return the count of status = 3 for each id
SQL SERVER VERSION
SELECT id, SUM(CASE WHEN status = 3 THEN 1 ELSE 0 END) as status_3_count
FROM yourtable
GROUP BY id
or just use a WHERE status = 3 and a COUNT(id)
Try a dependent subquery:
SELECT t1.*,
( SELECT count(*)
FROM sometable t2
WHERE t2.id = t1.id
AND t2.status = 3
) As somecolumnname
FROM sometable t1
WHERE t1.status=0
You can use a join for this. Write one query that will get all rows with a status zero:
SELECT *
FROM myTable
WHERE status = 0;
Then, write a subquery to get counts for the status of 3 for each id, by grouping by id:
SELECT COUNT(*)
FROM myTable
WHERE status = 3
GROUP BY id;
Since you want all the rows from the first table (at least that's what I am picturing), you can use a LEFT JOIN with the second table like this:
SELECT m.id, m.status, IFNULL(t.numStatus3, 0)
FROM myTable m
LEFT JOIN (SELECT id, COUNT(*) AS numStatus3
FROM myTable
WHERE status = 3
GROUP BY id) t ON m.id = t.id
WHERE m.status = 0;
The above will only show the count for rows containing an id that has status 0. Hopefully this is what you are looking for. If it is not, please post some sample data and expected results and I will help you try to reach it. Here is an SQL Fiddle example.

Combining two Count Queries into one

I have theses two queries
SELECT course,
COUNT(*) AS countp
FROM table1
WHERE pickout='Yes'
GROUP BY course
SELECT course,
COUNT(*) AS countw
FROM table1
WHERE pickout='Yes' AND result='Won'
GROUP BY course
what I am trying to achieve is a table with three columns Course, Countp, Countw but I am having trouble combining the two into one query.
Basically I am looking for a list of course with number of picks and then number of wins.
In MySQL the result of conditions evaluate to 1 or 0. You can sum that up
SELECT course,
sum(pickout='Yes') AS countp,
sum(pickout='Yes' AND result='Won') AS countw
FROM table1
GROUP BY course
Try the following SQL:
SELECT
Course,
COUNT(*) AS CountP,
SUM(CASE WHEN result='Won' THEN 1 ELSE 0 END) AS CountW
FROM table1
WHERE pickout = 'Yes'
GROUP BY Course
try this:
select a.course,a.countp ,b.countw from (SELECT course, COUNT(*) AS countp FROM table1 WHERE pickout='Yes' GROUP BY course)a full join
(SELECT course, COUNT(*) AS countw FROM table1 WHERE pickout='Yes' AND result='Won' GROUP BY course)b
a.course=b.course

left join two separate queries

I have two separate queries which pretty much return the same thing:
select id
from t
where id<>''
GROUP BY id
having count(*) >= 2;
select id
from t2
where id is not null
GROUP BY id
having count(*) >= 2
ORDER BY id ASC;
a list of ids whose values appear more than once. The first query returns more than the second, So I need to left join them somehow to get the results that are in the first query but not in the second. I tried to do a left join but it is not working properly.
I also tried the following to no avail:
select id
from t
where id<>''
GROUP BY id
having count(*) >= 2
not in (select id from t2 where id is not null GROUP BY id having count(*) >= 2
ORDER BY id ASC)
Additional Info
Query one is giving me all ids that have the same value for table 1 and query 2 is giving me all the same value ones for table 2. There are additional gotchas like there are some blank ids in table one while there are some nulls in table 2, hence the conditions excluding blanks for the former and nulls for the latter. So I get back these two separate results, which are almost the same, except in results 1 there are claims that arent in results 2 but only when these queries are run because they are duplicated in table 1 but not in table 2. although they do exist in table 2. So a simple left join where t1.id <> t2.id will not work because they do exist in t2.
You want to select ids in t1 that are not in t2. JOIN on t2 and ensure that the result is NULL.
SELECT t.id
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t2.id IS NULL
GROUP BY t.id
HAVING COUNT(t.id) > 1
SELECT t.id, t2.id FROM t
LEFT OUTER JOIN t2
ON t.id <> t2.id
WHERE t.id<>''
GROUP BY t.id having count(t.id) >= 2
ORDER BY t.id ASC
I assume your not in part before the subquery is actually mean that the id from the table t and t2 are not same and so added the condition t.id <> t2.id
EDIT
SELECT t.id FROM t
WHERE t.id<>''
AND t.id NOT IN (SELECT id FROM t2 where id is not null )
GROUP BY t.id having count(t.id) >= 2
ORDER BY t.id ASC
SQLFIDDLE