I have a question about Query using "Count" function.
I have a table : Student(id,name,age,sex)
I use sql query as:
Select name, age, count(id) as NumberOf
from Student
where sex = 'Boy'
group by age, name
And My DB:
1 | John | 12 | Boy |
2 | Mary | 13 | Girl |
3 | Alice | 15 | Girl |
I want to find a number of student is the same as age as well as boy.But it returns Null. I want it to return 0. How should? Thanks
I suppose you want this :
select name, age, sum(if(sex='Boy',1,0)) as NumberOf
from student
group by age, name;
name age NumberOf
John 12 1
Mary 13 0
Alice 15 0
P.S. deliberately I put sum due to probability of existence of duplicated record for name and age.
You can do this without if :
select name, age, sum(sex='Boy') as NumberOf
from student
group by age, name;
Related
If I have these different tables:
Participants_1
name | age
James | 18
Participants_2
name | age
Daniel | 20
James | 18
How can I insert it to another table like this?
All_Participants
name | age | in_participants_1 | in_participants_2
James | 18 | 1 | 1
Daniel | 20 | 0 | 1
So basically the All_Participants tables is the collection of all rows from other Participants tables with additional fields of is_participants_* if they came from specific tables.
You need a UNION ALL with GROUP BY:
-- INSERT INTO ...
SELECT name, age, MAX(in_participants_1), MAX(in_participants_2)
FROM (
SELECT name, age, 1 AS in_participants_1, 0 AS in_participants_2 FROM participants_1
UNION ALL
SELECT name, age, 0, 1 FROM participants_2
) AS u
GROUP BY name, age
Ideally you would store all participants in one table and store their ids in participants 1 and 2 table. Or better, create one participation table that stores participant id and event id.
This is my simplified table
year | teacher
1 | john
2 | john
2 | sam
3 | john
3 | simon
When I run the query below
SELECT year, teacher FROM table1 GROUP BY year
It gives me the result :
year | teacher
1 | john
2 | john
3 | john
In this case, year column is fine as it shows all distinct value, however teacher column is still repeated. I wish to have distinct values on teacher columns too.
Output I am looking for :
year | teacher
1 | john
2 | sam
3 | simon
This query is not valid SQL (even if MySQL happens to accept it):
SELECT year, teacher
FROM table1
GROUP BY year;
You need an aggregation function around teacher:
SELECT year, MAX(teacher)
FROM table1
GROUP BY year;
That said, this doesn't do what you want. That is hard to do in a single query. Instead, use two queries:
SELECT DISTINCT year FROM table1;
SELECT DISTINCT teacher FROM table1;
I have several fields in a sql table, including name, type, and date. In date, it is stored as a string "2016-05-01" format. I would like to count the number of occurrences of name grouped by each quarter date.
By this, I mean that name can occur multiple times in a month. I would like to count the number of times the names occur in groups of 3 months (quarters) and print the name, count, and quarter in each row.
So if for example I had the columns name, type, and date and ran the query
it could result in
Name Quarter Count
Ron | 1 | 62 |
Ron | 2 | 32 |
Ron | 3 | 45 |
Ron | 4 | 33 |
Tim | 1 | 62 |
Tim | 3 | 62 |
and so on. Thanks
Assuming that my_date_column is a date
You can use quarter()
select Name, QUARTER(my_date_column), count(*)
frpm my_table
group by name, QUARTER(my_date_column)
;
otherwise you should convert the string in date
for convert a string you can use
str_to_date('2016-09-20', '%Y-%m-%d')
select Name, QUARTER(str_to_date(my_strdate_column, '%Y-%m-%d')), count(*)
frpm my_table
group by name, QUARTER(str_to_date(my_strdate_column, '%Y-%m-%d'))
;
I have a data like this,
Name |Exam_ID|Score
------+-------+------
Matt |12 | 87
Matt |12 | 85
Andy |10 | 89
Lisa |11 | 32
Lisa |11 | 68
Andy |11 | 38
Matt |10 | 70
Lisa |10 | 87
I want to SUM those score, but only those with different name and exam_id. If there's more than one same exam_id on same name, it will took the highest score. The end result I want like this:
Name |Score
------+------
Matt | 157
Andy | 127
Lisa | 155
Matt got 3 scores (87, 85, 70). But since 87 and 85 using same exam_id, I need to only take the highest score and SUM it with different score that got different exam_id which make his total score are 87+70 = 157
I've been trying using MAX, but I can't get it like that
SELECT Name, MAX(Exam_ID), SUM(Score) from RESULT
group by NAME;
You need two levels of aggregation:
select name, sum(max_score)
from (select name, exam_id, max(score) as max_score
from result
group by name, exam_id
) ne
group by name;
You'll need to exploit the structured part of structured query language, and make a two-level query
SELECT Name, SUM(Score) AS Score
FROM (
SELECT Name, Exam_ID, MAX(Score) AS Score
FROM Result
GROUP BY Name
) BestScoresPerExam
GROUP BY Name
The inner query gets the best score for each exam. The outer one sums the scores.
try this...
select name, exam_id, sum(Score) as max_score from result group by name, exam_id
I've got a table containing persons gender-coded as 0 and 1. I need to select every other row as male/female. I thought I could manage this somehow by using modulo and the gender-codes 0 and 1, but I haven't managed to figure it out yet...
The result I'm looking for would look like this:
+-----+--------+-------+
| row | gender | name |
+-----+--------+-------+
| 1 | female | Lisa |
| 2 | male | Greg |
| 3 | female | Mary |
| 4 | male | John |
| 5 | female | Jenny |
+-----+--------+-------+
etc.
The alternative is to do it in PHP by merging 2 separate arrays, but I would really like it as a SQL query...
Any suggestions are appreciated!
Do two subqueries to select male and female. Use ranking function to have them enumerated.
Males:
1 | Peter
2 | John
3 | Chris
Females:
1 | Marry
2 | Christina
3 | Kate
Then multiplay ranking result by x10 and add 5 for females. So you have this:
Males:
10 | Peter
20 | John
30 | Chris
Females:
15 | Marry
25 | Christina
35 | Kate
Then do the UNION ALL and sort by new sort order/new ID.
Together it should like this (pseudo code)
SELECT
Name
FROM
(subquery for Males: RANK() AS sortOrd, Name)
UNION ALL
(subquery for Females: RANK()+1 AS SortOrd, Name)
ORDER BY SortOrd
Result should be like this:
Males and Females:
10 | Peter
15 | Marry
20 | John
25 | Christina
30 | Chris
35 | Kate
Found Emulate Row_Number() and modified a bit for your case.
set #rownum := 0;
set #pg := -1;
select p.name,
p.gender
from
(
select name,
gender,
#rownum := if(#pg = gender, #rownum+1, 1) as rn,
#pg := gender as pg
from persons
order by gender
) as p
order by p.rn, p.gender
Try on SQL Fiddle
Note: From 9.4. User-Defined Variables
As a general rule, you should never assign a value to a user variable
and read the value within the same statement. You might get the
results you expect, but this is not guaranteed.
I will leave it up to you do decide if you can use this. I don't use MySQL so I can't really tell you if you should be concerned or not.
Similar to Mikael's solution but without the need to order the resultset multiple times -
SELECT *
FROM (
SELECT people.*,
IF(gender=0, #mr:=#mr+1, #fr:=#fr+1) AS rank
FROM people, (SELECT #mr:=0, #fr:=0) initvars
) tmp
ORDER BY rank ASC, gender ASC;
To avoid having to order both the inner and outer selects I have used separate counters (#mr - male rank, #fr - female rank) in the inner select.
I've got a table containing persons gender-coded as 0 and 1
Then why would you make assumptions on the order of rows in the result set? Seems to me transforming the 0/1 into 'male'/'female' is far more robust:
select name, case gender when 0 then 'male' else 'female' end
from Person
SELECT alias.*, ROW_NUMBER() OVER (PARTITION BY GENDER ORDER BY GENDER) rnk
FROM TABLE_NAME
ORDER BY rnk, GENDER DESC