MYSQL - count occurrence of variable in specific columns only - mysql

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;

Related

how to select all of duplicate record in mysql

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

MySQL select unique rows in two columns with the highest value in one column

I have a basic table:
+-----+--------+------+------+
| id, | name, | cat, | time |
+-----+--------+------+------+
| 1 | jamie | 1 | 100 |
| 2 | jamie | 2 | 100 |
| 3 | jamie | 1 | 50 |
| 4 | jamie | 2 | 150 |
| 5 | bob | 1 | 100 |
| 6 | tim | 1 | 300 |
| 7 | alice | 4 | 100 |
+-----+--------+------+------+
I tried using the "Left Joining with self, tweaking join conditions and filters" part of this answer: SQL Select only rows with Max Value on a Column but some reason when there are records with a value of 0 it breaks, and it also doesn't return every unique answer for some reason.
When doing the query on this table I'd like to receive the following values:
+-----+--------+------+------+
| id, | name, | cat, | time |
+-----+--------+------+------+
| 1 | jamie | 1 | 100 |
| 4 | jamie | 2 | 150 |
| 5 | bob | 1 | 100 |
| 6 | tim | 1 | 300 |
| 7 | alice | 4 | 100 |
+-----+--------+------+------+
Because they are unique on name and cat and have the highest time value.
The query I adapted from the answer above is:
SELECT a.name, a.cat, a.id, a.time
FROM data A
INNER JOIN (
SELECT name, cat, id, MAX(time) as time
FROM data
WHERE extra_column = 1
GROUP BY name, cat
) b ON a.id = b.id AND a.time = b.time
The issue here is that ID is unique per row you can't get the unique value when getting the max; you have to join on the grouped values instead.
SELECT a.name, a.cat, a.id, a.time
FROM data A
INNER JOIN (
SELECT name, cat, MAX(time) as time
FROM data
WHERE extra_column = 1
GROUP BY name, cat
) b ON A.Cat = B.cat and A.Name = B.Name AND a.time = b.time
Think about it... So what ID is mySQL returning form the Inline view? It could be 1 or 3 and 2 or 4 for jamie. Hows does the engine know to pick the one with the max ID? it is "free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. " it could pick the wrong one resulting in incorrect results. So you can't use it to join on.
https://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html
If you want to use a self join, you could use this query:
SELECT
d1.*
FROM
date d1 LEFT JOIN date d2
ON d1.name=d2.name
AND d1.cat=d2.cat
AND d1.time<d2.time
WHERE
d2.time IS NULL
It is very simple
SELECT MAX(TIME),name,cat FROM table name group by cat

Check multiple columns for duplicate and list all records

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`

How can I get a history like query on MySQL?

I'd like a little help here.
I'm building a database in MySQL where I will have a bunch of different activities. Each activity is part of a list.
So, I have the following tables on my database.
List
id
name
Activity
id
name
idList (FK to List)
I also want to know when each activity is finished (you can finish the same activity many times). To accomplish that, I have another table:
History
date
idActivity (FK to activity)
When the user finishes an activity, I add the id of this activity and the current time the activity was finished, to the History table.
I want to get the entire list with the date it was finished. When an activity has not been finished, I want it to show the date as null.
But, getting the list just once is easy. A simple Left Outer Join will do the trick. My issue here is that I want to get the ENTIRE list everytime a date appears on the history table.
This is what I'm looking for:
List:
id | name
1 | list1
Activity:
id | name | idList
1 | Activity1 | 1
2 | Activity2 | 1
3 | Activity3 | 1
4 | Activity4 | 1
5 | Activity5 | 1
6 | Activity6 | 1
History:
date | idActivity
17/07/14 | 1
17/07/14 | 3
17/07/14 | 4
17/07/14 | 6
16/07/14 | 2
16/07/14 | 3
16/07/14 | 5
Expected Result:
idActivity | idList | activityName | date
1 | 1 | Activity1 | 17/07/14
2 | 1 | Activity2 | NULL
3 | 1 | Activity3 | 17/07/14
4 | 1 | Activity4 | 17/07/14
5 | 1 | Activity5 | NULL
6 | 1 | Activity6 | 17/07/14
1 | 1 | Activity1 | NULL
2 | 1 | Activity2 | 16/07/14
3 | 1 | Activity3 | 16/07/14
4 | 1 | Activity4 | NULL
5 | 1 | Activity5 | 16/07/14
6 | 1 | Activity6 | NULL
The "trick" is to use a CROSS JOIN (or semi-cross join) operation with a distinct list of dates from the history table, to produce the set of rows you want to return.
Then a LEFT JOIN (outer join) to the history table to find the matching history rows.
Something like this:
SELECT a.id AS idActivity
, a.idList AS idList
, a.name AS activityName
, h.date AS `date`
FROM activity a
CROSS
JOIN ( SELECT s.date
FROM history s
GROUP BY s.date
) r
LEFT
JOIN history h
ON h.idActivity = a.id
AND h.date = r.date
ORDER
BY r.date
, a.id
That query gets the six rows from activity, and two rows (distinct values of date) from history (inline view aliased as r). The CROSS JOIN operation matches each of the six rows with each of the two rows, to produce a Cartesian product of 12 rows.
To get the rows returned in the specified order, we order by date, and then by activity.id.

Remove duplicates from one column keeping whole rows

id | userid | total_points_spent
1 | 1 | 10
2 | 2 | 15
3 | 2 | 50
4 | 3 | 5
5 | 1 | 15
With the above table, I would first like to remove duplicates of userid keeping the rows with the largest total_points_spent, like so:
id | userid | total_points_spent
3 | 2 | 50
4 | 3 | 5
5 | 1 | 15
And then I would like to sum the values of total_points_spent, which would be the easy part, resulting in 70.
I am not really sure the "remove" you meant is to delete or to select. Here is the query for select only max totalpointspend record respectively.
SELECT tblA.*
FROM ( SELECT userid, MAX(totalpointspend) AS maxtotal
FROM tblA
GROUP BY userid ) AS dt
INNER JOIN tblA
ON tblA.userid = dt.userid
AND tblA.totalpointspend = dt.maxtotal
ORDER BY tblA.userid