I have one table named colors and I need to create a query that returns how many unique colors are used each year based on the date in my other table, programs.
It looks like this:
colors
+----+----------+
| id | name |
+----+----------+
| 1 | blue |
| 2 | yellow |
+----+----------+
programs
+----+------------+
| id | date |
+----+------------+
| 1 | 2016-01-08 |
| 2 | 2016-02-08 |
| 3 | 2017-02-08 |
+----+------------+
programs_colors
+------------+----------+
| program_id | color_id |
+------------+----------+
| 1 | 1 |
| 1 | 1 |
| 2 | 2 |
| 2 | 1 |
| 3 | 1 |
| 3 | 1 |
+------------+----------+
I have tried with this:
SELECT min(date), count(*) FROM (
SELECT min(date) AS date FROM programs_colors INNER JOIN programs ON programs.id = program_id GROUP BY color_id
) AS a GROUP BY year(date)
min(date): count(*):
2016-01-08 2
2017-01-08 0
But the above query groups my colors as a whole, but I need them grouped by each year
Expected result:
min(date): count(*):
2016-01-08 2
2017-01-08 1
I hope my question makes sense
SELECT min(date), count(distinct color_id)
FROM programs_colors
INNER JOIN programs
ON programs.id = program_id
GROUP BY year(date);
If I understand right, you might need to do something like this
SELECT min(date), sum(count) FROM (
SELECT min(date) AS date, count(*) as count FROM programs_colors INNER JOIN programs ON programs.id = program_id GROUP BY color_id
) AS a GROUP BY year(date)
Related
Suppose I have a table like this:
Order_ID | Box_ID | Item_ID
------------------------------------
B | 1 | b
B | 2 | b
A | 2 | a
A | 3 | a
A | 4 | a
Now when I order the table by order ID,
SELECT * FROM table ORDER BY Order_ID, Box_ID;
the result will look like this:
Order_ID | Box_ID | Item_ID
------------------------------------
A | 2 | a
A | 3 | a
A | 4 | a
B | 1 | b
B | 2 | b
But now, I want the sql statement to first consider putting same value of Box_ID together,
such that the result will look like this:
Order_ID | Box_ID | Item_ID
------------------------------------
A | 2 | a
B | 2 | b
// despite order_ID being B, but box_ID is equal to previous value, so group together
A | 3 | a
A | 4 | a
B | 1 | b
But the following code,
SELECT * FROM table ORDER BY Box_ID, Order_ID
Will produce the following result since it lists Box_ID in alphabetical order first.
Order_ID | Box_ID | Item_ID
------------------------------------
B | 1 | b
A | 2 | a
B | 2 | b
A | 3 | a
A | 4 | a
How can I output my desired result?
I think you want:
order by min(order_id) over(partition by box_id), box_id
In earlier versions, you can use a subquery:
select *
from mytable t
order by
(select min(order_id) from mytable t1 where t1.box_id = t.box_id),
box_id
In order versions of MySQL, you can use a correlated subquery:
select t.*
from table t
order by (select min(t2.order_id) from table t2 where t2.box_id = t.box_id),
box_id;
If you want the rows with most occurrences of Box_ID at the top, then you need this query:
SELECT Box_ID, COUNT(*) counter
FROM tablename
GROUP BY Box_ID
joined to the table like this:
SELECT t.*
FROM tablename t
INNER JOIN (
SELECT Box_ID, COUNT(*) counter
FROM tablename
GROUP BY Box_ID
) g ON g.Box_ID = t.Box_ID
ORDER BY g.counter DESC, Order_ID, Box_ID
See the demo.
Results:
> Order_ID | Box_ID | Item_ID
> :------- | -----: | :------
> A | 2 | a
> B | 2 | b
> A | 3 | a
> A | 4 | a
> B | 1 | b
I have the following result set...
Name | Team | Score
A | 1 | 10
B | 1 | 11
C | 2 | 9
D | 2 | 15
and I want to add an extra column to the results set for the team score so I can sort on it and end up with the following data set...
Name | Team | Score | TeamScore
D | 2 | 15 | 24
C | 2 | 9 | 24
B | 1 | 11 | 21
A | 1 | 10 | 21
So I end up with the top team first with the members in order.
My actual data is way more complicated than this and pulls in data from several tables but if you can solve this one I can solve my bigger issue!
Join the table to a query that returns the total for each team:
select t.*, s.teamscore
from tablename t
inner join (
select team, sum(score) teamscore
from tablename
group by team
) s on s.team = t.team
order by s.teamscore desc, t.team, t.score desc
See the demo.
Results:
| Name | Team | Score | teamscore |
| ---- | ---- | ----- | --------- |
| D | 2 | 15 | 24 |
| C | 2 | 9 | 24 |
| B | 1 | 11 | 21 |
| A | 1 | 10 | 21 |
In MySQL 8+, we can simplify and just use SUM as an analytic function:
SELECT
Name,
Team,
Score,
SUM(Score) OVER (PARTITION BY Team) AS TeamScore
FROM yourTable
ORDER BY
TeamScore DESC,
Score;
How do I sort a table by it's minimum value per group but at the same time keep a group of rows together. Below a simple example of what i am trying to accomplish. The table is sorted by the lowest group value, but the group remains together. I am pretty sure this question has been asked already but i could not find an answer.
+---------+-------+
| Group | value |
+---------+-------+
| 1 | 3.99 |
| 1 | 10.99 |
| 3 | 12.69 |
| 1 | 20.95 |
| 2 | 19.95 |
| 3 | 10.09 |
+---------+-------+
Desired output
+---------+-------+
| Group | value |
+---------+-------+
| 1 | 3.99 |
| 1 | 10.99 |
| 1 | 20.95 |
| 3 | 10.69 |
| 3 | 12.09 |
| 2 | 19.95 |
+---------+-------+
If you are running MySQL 8.0, you can sort with window functions:
select t.*
from mytable t
order by min(value) over(partition by grp), value
In earlier versions, one option is to join an aggregate subquery:
select t.*
from mytable t
inner join (
select grp, min(value) min_value from mytable group by grp
) m on m.grp = t.grp
order by m.min_value, t.value
SELECT *,RN = ROW_NUMBER() OVER (PARTITION BY ID ORDER BY VALUE,ID) FROM TEMP
Imagine this table t1,
+----------+-------+--------+
| group_id | name | age |
+----------+-------+--------+
| 1 | A1 | 1 |
| 1 | A2 | 2 |
| 1 | A3 | 3 |
| 2 | B1 | 4 |
+----------+-------+--------+
Using the following query in MySQL,
SELECT group_id, name, COUNT(*) FROM t1 GROUP BY group_id
we get,
+----------+-------+--------+----------+
| group_id | name | age | COUNT(*) |
+----------+-------+--------+----------+
| 1 | A1 | 2 | 3 |
| 2 | B1 | 4 | 1 |
+----------+-------+--------+----------+
As you can see here, it's possible that values name=A1 and age=2 are not from the same record.
My question is, how can I control which single results form the name and age columns are shown, so the content is from one record? Is there a way to sort them in some way? Fro example sorting by age in reverse order would give
+----------+-------+--------+----------+
| group_id | name | age | COUNT(*) |
+----------+-------+--------+----------+
| 1 | A3 | 3 | 3 |
| 2 | B1 | 4 | 1 |
+----------+-------+--------+----------+
Thanks.
I don't know why do you say that your query works. You should also group by name...
SELECT group_id, name, COUNT(*) FROM t1 GROUP BY group_id, name
If you want to get only one of them, try:
SELECT group_id, MIN(name), COUNT(*) FROM t1 GROUP BY group_id
I don't know about full control, but you can do like this
SELECT student_name, MIN(test_score), MAX(test_score)
FROM student
GROUP BY student_name;
SELECT group_id, name, COUNT(*)
FROM t1
WHERE name IN ( 'xxx', 'yyy', ..., 'zzz' )
GROUP BY group_id
SORT BY COUNT(*)
How to select 1st, 2nd or 3rd value before MAX ?
usually we do it with order by and limit
SELECT * FROM table1
ORDER BY field1 DESC
LIMIT 2,1
but with my current query I don't know how to make it...
Sample table
+----+------+------+-------+
| id | name | type | count |
+----+------+------+-------+
| 1 | a | 1 | 2 |
| 2 | ab | 1 | 3 |
| 3 | abc | 1 | 1 |
| 4 | b | 2 | 7 |
| 5 | ba | 2 | 1 |
| 6 | cab | 3 | 9 |
+----+------+------+-------+
I'm taking name for each type with max count with this query
SELECT
`table1b`.`name`
FROM
(SELECT
`table1a`.`type`, MAX(`table1a`.`count`) AS `Count`
FROM
`table1` AS `table1a`
GROUP BY `table1a`.`type`) AS `table1a`
INNER JOIN
`table1` AS `table1b` ON (`table1b`.`type` = `table1a`.`type` AND `table1b`.`count` = `table1a`.`Count`)
and I want one more column additional to name with value before max(count)
so result should be
+------+------------+
| name | before_max |
+------+------------+
| ab | 2 |
| b | 1 |
| cab | NULL |
+------+------------+
Please ask if something isn't clear ;)
AS per your given table(test) structure, the query has to be as follows :
select max_name.name,before_max.count
from
(SELECT type,max(count) as max
FROM `test`
group by type) as type_max
join
(select type,name,count
from test
) as max_name on (type_max.type = max_name.type and count = type_max.max )
left join
(select type,count
from test as t1
where count != (select max(count) from test as t2 where t1.type = t2.type)
group by type
order by count desc) as before_max on(type_max.type = before_max .type)