My records is:
name | id | AVG(point) as point
a | 1 | 6
b | 2 | 6
c | 3 | 5
d | 4 | 5
e | 5 | 4
f | 6 | 3
g | 7 | 2
How to select record below:
1.I want to select top 3 record, result follow:
name | id | AVG(point) as point
a | 1 | 6
b | 2 | 6
c | 3 | 5
d | 4 | 5
e | 5 | 4
2.I want to select record not into top 3, result follow:
name | id | AVG(point) as point
f | 6 | 3
g | 7 | 2
How can I do?
There are several ways to do these. Here's a couple using in and not in.
For the top 3, you can use in:
select *
from yourtable
where point in (select distinct point
from yourtable
order by 1 desc
limit 3)
For the rest, use not in instead:
select *
from yourtable
where point not in (select distinct point
from yourtable
order by 1 desc
limit 3)
Other methods include exists with not exists and distinct with joins.
select *
from yourtable as t1
inner join (select distinct point
from yourtable
order by 1 desc
limit 3) as t2
on t1.point = t2.point
For the second part of your question, do not use
desc
Related
I searched for this answer but couldn't find anything. Hoping for a little help.
Query Needed: How many times does each number appear in each column.
tableName = "Schedule"
+-----+-------+-----------+-------+
| key | prime | secondary | third |
+-----+-------+-----------+-------+
| 1 | 6 | 6 | 7 |
| 2 | 7 | 9 | 9 |
| 3 | 6 | 9 | 6 |
| 4 | 9 | 9 | 9 |
+-----+-------+-----------+-------+
I would like my results to be a count of each occurrence in each column...
+--------+------ +-----------+-------+
| number | prime | secondary | third |
+--------+-------+-----------+-------+
| 6 | 2 | 1 | 1 |
| 7 | 1 | 0 | 1 |
| 9 | 1 | 3 | 2 |
+-------+-----------+--------+-------+
So the #6 is occurs 2x in "prime" column, occurs 1x in the "secondary" column and occurs 1x in the "third" column.
Get all the distinct numbers from the three columns using union. left join the count of each column to these numbers to get the final result.
select all_nums.num,coalesce(p_cnt,0), coalesce(s_cnt,0), coalesce(t_cnt,0)
from
(select prime as num from t union select secondary from t union select third from t) all_nums
left join
(select prime,count(*) as p_cnt from t group by prime) p on p.prime=all_nums.num
left join
(select secondary,count(*) as s_cnt from t group by secondary) s on s.secondary=all_nums.num
left join
(select third,count(*) as t_cnt from t group by third) t on t.third=all_nums.num
group by all_nums.num
select nall.id,
(select count(*) from Schedule where prime = nall.id) as prime,
(select count(*) from Schedule where secondary = nall.id) as secondary,
(select count(*) from Schedule where third = nall.id) as third
from
(select prime as id from Schedule
union
select secondary as id from Schedule
union
select third as id from Schedule ) nall;
I have a table with columns ID, Content and Day. I am trying to find all rows that have duplicate Content and Day values and display all rows
SELECT ID,Content, `Day`, Count(*)
FROM table
GROUP BY Content,`Day`
HAVING COUNT(*) > 1
The current code will return a list of duplicate Content and 'Day' values for instance:
ID|Content|Day
1 | a | 1
2 | a | 1
3 | a | 1
4 | b | 2
5 | b | 2
6 | c | 3
7 | c | 4
Will result in:
ID|Content|Day|Count
1 | a | 1 | 3
4 | b | 2 | 2
But I want to display all the unique IDs as well;
ID|Content|Day
1 | a | 1
2 | a | 1
3 | a | 1
4 | b | 2
5 | b | 2
Just make a Sub-Query
select *
from table
where `day` in
(
SELECT ID
FROM table
GROUP BY Content,`Day`
HAVING COUNT(*) > 1
) A
Use that query as a subquery to join against the table again:-
SELECT table.ID, table.Content, table.`Day`
FROM table
INNER JOIN
(
SELECT Content, `Day`, Count(*)
FROM table
GROUP BY Content,`Day`
HAVING COUNT(*) > 1
) sub0
ON sub0.Content = table.Content
AND sub0.`Day` = table.`Day`
I have the following table:
+----+-----------+-----------+
| id | teacherId | studentId |
+----+-----------+-----------+
| 1 | 1 | 4 |
| 2 | 1 | 2 |
| 3 | 1 | 1 |
| 4 | 1 | 3 |
| 5 | 2 | 2 |
| 6 | 2 | 1 |
| 7 | 2 | 3 |
| 8 | 3 | 9 |
| 9 | 3 | 6 |
| 10 | 1 | 6 |
+----+-----------+-----------+
I need a query to find two teacherId's with maximum number of common studentId's.
In this case teachers with teacherIds 1,2 have common students with studentIds 2, 1, 3, which is greater than 1,3 having common students 6.
Thanks in Advance!
[Edit]: After several hours I've had the following solution:
SELECT * FROM (
SELECT r1tid, r2tid, COUNT(r2tid) AS cnt
FROM (
SELECT r1.teacherId AS r1tid, r2.teacherId AS r2tid
FROM table r1
INNER JOIN table r2 ON r1.studentId=r2.studentId AND r1.teacherId!=r2.teacherId
ORDER BY r1tid
) t
GROUP BY r1tid, r2tid
ORDER BY cnt DESC
) t GROUP BY cnt ORDER BY cnt DESC LIMIT 1;
I was sure that there must exist more short and elegant solution, but I could not find it.
You would do this with a self-join. Assuming no duplicates in the table:
select t.teacherid, t2.teacherid, count(*) as NumStudentsInCommon
from table t join
table t2
on t.studentid = t2.studentid and
t.teacherid < t2.teacherid
group by t.teacherid, t2.teacherid
order by NumStudentsInCommon desc
limit 1;
If you had duplicates, you would just replace count(*) with count(distinct studentid), but count(distinct) requires a bit more work.
select t.teacherId, t2.teacherId, sum(t.studentId) as NumStudentsInCommon
from table1 t join
table1 t2
on t.studentId = t2.studentId and
t.teacherId < t2.teacherId
group by t.teacherId, t2.teacherId
order by NumStudentsInCommon desc
Table Mytable1
Id | Actual
1 ! 10020
2 | 12203
3 | 12312
4 | 12453
5 | 13211
6 | 12838
7 | 10l29
Using the following syntax:
SELECT AVG(Actual), CEIL((#rank:=#rank+1)/3) AS rank FROM mytable1 Group BY rank;
Produces the following type of result:
| AVG(Actual) | rank |
+-------------+------+
| 12835.5455 | 1 |
| 12523.1818 | 2 |
| 12343.3636 | 3 |
I would like to take AVG(Actual) column and UPDATE a second existing table Mytable2
Id | Predict |
1 | 11133
2 | 12312
3 | 13221
I would like to get the following where the Actual value matches the ID as RANK
Id | Predict | Actual
1 | 11133 | 12835.5455
2 | 12312 | 12523.1818
3 | 13221 | 12343.3636
IMPORTANT REQUIREMENT
I need to set an offset much like the following syntax:
SELECT #rank := #rank + 1 AS Id , Mytable2.Actual FROM Mytable LIMIT 3 OFFSET 4);
PLEASE NOTE THE AVERAGE NUMBER ARE MADE UP IN EXAMPLES
you can join your existing query in the UPDATE statement
UPDATE Table2 T2
JOIN (
SELECT AVG(Actual) as AverageValue,
CEIL((#rank:=#rank+1)/3) AS rank
FROM Table1, (select #rank:=0) t
Group BY rank )T1
on T2.id = T1.rank
SET Actual = T1.AverageValue
Consider this table:
I need to make a SQL query which returns highlighted rows. In other words: rows which are linked to each other by idContactTo.
Example:
1 has contact to 2, 2 has contact to 1 - they are linked and should be in result table. But even 1 has contact to 3 it doesn't mean that 3 has contact to 1 - they aren't linked.
You can do it via INNER JOIN,
SELECT a.*
FROM tableName a
INNER JOIN tableName b
ON a.idContantOwner = b.idContactTo AND
b.idContantOwner = a.idContactTo
SQLFiddle Demo
Another way to do it
SELECT t.*
FROM
(
SELECT MiN(id) min_id, MAX(id) max_id
FROM Table1
GROUP BY LEAST(idContactOwner, idContactTo),
GREATEST(idContactOwner, idContactTo)
HAVING COUNT(*) = 2
) q JOIN Table1 t
ON t.id IN(q.min_id, q.max_id)
Output:
| ID | IDCONTACTOWNER | IDCONTACTTO |
|----|----------------|-------------|
| 1 | 1 | 2 |
| 2 | 2 | 1 |
| 4 | 3 | 4 |
| 5 | 4 | 3 |
Here is SQLFiddle demo