If I have a database of first names and annual incomes for two years as enumerated columns (I know this is poor database design but I don't have the liberty to change it at the moment). For example:
Name_2000, Name_2010, Income_2000, Income_2010
How can I construct a query to return all the unique names in both name columns in the first result column. The second result column should be the sum of all incomes for that name for 2000. The third should be the sum of all incomes for that name for 2010.
Obviously, in this example a person (record) may change names between years or not have a name in either year too.
Can I do this in a single query? The ability to filter by a certain subset of names would also be handy..
I would suggest using a sub query that unions 2 results together, one for each set of names and incomes, but each returning a dummy 0 for the income for the other year.
Something like this:-
SELECT aname, SUM(aincome2000), SUM(aincome2010)
FROM
(
SELECT Name_2000 AS aname, Income_2000 AS aincome2000, 0 AS aincome2010
FROM sometable
UNION ALL
SELECT Name_2010 AS aname, 0 AS aincome2000, Income_2010 AS aincome2010
FROM sometable
) sub1
GROUP BY aname
Related
GROUP BY: If you want, you can take the rows that remain after WHERE and put them in groups or buckets, where each group contains the same value for the GROUP BY expression (and all the other rows are put in a list for that group). In Java, you would get something like: Map<String, List<Row>>. If you do specify a GROUP BY clause, then your actual rows contain only the group columns, no longer the remaining columns, which are now in that list. Those columns in the list are only visible to aggregate functions that can operate upon that list.
This above paragraph was taken from: https://blog.jooq.org/a-beginners-guide-to-the-true-order-of-sql-operations/
We have a table named student that has the following fields :
Student_id
Student_name
Student_marks
Student_branch
I write a query as:
select sum(student_marks) from student
group by student_branch;
So according to the paragraph, I am grouping the rows by student_branch.
So what group is created?
Is there a group that contains all of the student_branch values?
Also I couldn't get the meaning of this sentence '(and all the other rows are put in a list for that group).'
Can anyone please explain how does group by actually work and then how do the aggregate functions work on those groups.
In your example you would have a separate group for each distinct value in the column student_branch. So if you you have student_branch = A for 5 students and student_branch = B for 3 students, then you would get 2 groups:
A with 5 records
B with 3 records
When you use aggregate functions, they will operate on all records within one group. So SUM(student_marks) will add all student marks of the students in group A separately, and also in group B separately.
In your sample query you will get 2 aggregated result rows, with only the sums of the marks. The result would be more meaningful, if you include the student_branch in the SELECT clause, like:
SELECT student_branch, SUM(student_marks) AS sum_of_marks FROM student
GROUP BY student_branch;
Then the result would look like:
student_branch
sum_of_marks
A
15 (random number, = sum of marks for A students)
B
8 (random number, = sum of marks for B students)
The GROUP BY will only group the records which remain after filtering the data with the WHERE clause. In your example case there is no WHERE clause, so it will group the records of the whole table by student branch.
I am currently trying to query a table based off two fields, one with a date and the other with records to be counted. The results of the query would list the months as numbers (January = 1, Feb = 2, etc) in one column and the other would list the total number of the individual UNIQUE records. The following query I have;
SELECT DISTINCT Month([Date Received]) AS [Month], Count([1 TeamTracking].[Asset #]) AS [CountOfAsset #]
FROM [1 TeamTracking]
GROUP BY Month([Date Received]);
To test out and make sure I have the right numbers I exported the data to an Excel file and removed duplicates based off of the date and Asset # field. There can be multiple duplicate Asset #'s in the month and there can be the same Asset # in other months. I only want to count the Asset # once per month and not any duplicates in that month. It should be counted again if it is in a different month. For example this is the results I would expect with the query:
1 Team Tracking Table:
Results:
I've tried and just don't get the right numbers. I've tried both in the property field setting the unique values and records to yes and no luck there either. Any assistance would be appreciated. Thank you.
This needs a nested subquery that first consolidates data to unique records. That query then is source for outer query that counts records.
Assuming dates are always first of each month and data is multi-year, consider:
SELECT DateReceived, Count(*) AS Count FROM (
SELECT DISTINCT DateReceived, IDnum FROM Tracking)
GROUP BY DateReceived;
If dates are not always first of month and data is multi-year, consider:
SELECT YearMo, Count(*) AS Count FROM (
SELECT DISTINCT Format(DateReceived, "yyyymm") AS YearMo, IDnum FROM Tracking)
GROUP BY YearMo;
If data is not multi-year:
SELECT Month, Count(*) AS Count FROM (
SELECT DISTINCT Month(DateReceived) AS Month, IDnum FROM Tracking)
GROUP BY Month;
Strongly advise not to use spaces nor punctuation/special characters in naming convention, nor reserved words as names. If you do, must enclose in [ ].
I have a table structure
id group name points
1 1 a 10
2 1 b 9
3 2 c 7
and so on..
I am writing a query which gives me an array of names and avg of all the points for seleceted rows where group matches the value
for group_list = [1] want a results like this [name: ['a','b'], median:[9.5]]
I have tried like this
$group_list = [1];
createQueryBuilder()
->select('x.name as name, x.AVG(points) as median')
->from('myTable', 'x')
->where('x.group IN(:groupList)')
->setParameter('groupList', $group_list)
->getQuery()
->getResult();
Need some help with this
You are combining 2 distinct requirements into a single sql statement and this causes the problem.
The average of points is a single value per group or per all records, while the names are a list. You can combine the 2 into a single query by repeating the averages across the names, however, it just generates an overhead.
I would simply run a query to get the list of usernames and a separate one to get the average points (either grouped by groups or across all groups, this is not clear from the question).
This solution is so simple, that I do not think I need to provide any code.
Alternatively, you can use MySQL's group_concat() function to get the list of names per group into in single value in comma separated list (you can use any other separator character in place of comma). In this case it is more worthwile to combine the 2 in a single query:
select group_concat(`name`) as names, avg(`points`) as median
from mytable
where `group` in (...)
If you want names from more than one groups, then add group field to the select and group by lists:
select `group`, group_concat(`name`) as names, avg(`points`) as median
from mytable
where `group` in (...)
group by `group`
You should add a group by
->groupBy('x.`group`')
I have a table which has 3 columns (name, course, grade).
My 'name' column contains three students.
I need to sum grades of every student and divide it by the amount of grades.
I'm trying to do something like this,
SELECT
name
FROM
table
GROUP BY
name
AND
(SELECT SUM(grade) FROM table / SELECT COUNT(grade) FROM table GROUP BY name)
I'm not a native english speaker, so I hope you understand me.
I expect you want to calculate the average grade?
SELECT name, AVG(grade)
FROM `table`
GROUP BY name
your table design does not follow the 1st rule of normalization: atomicity. You have multiple names in single column AND you want to process them separately. This makes querying more difficult and inefficient. You need to normalize your table.
I need to select records from 2 tables, one called cities and one called neighborhoods. They both share a table column in common called parent_state. In this cell the id of the parent state is stored.
I need to select all cities and neighborhoods that belong to a certain state. For example if the state id is 10, I need to get all the cities and neighborhoods that has this value for it's parent_state cell.
The state id is stored in a PHP variable like so:
$parent_state = '10';
What would this query look like (preferably the merged results from both tables should be sorted by the column name in alphabetical order)?
EDIT
Yes, I probably do need a union. I'm very new to mysql and all I can do at the moment is query tables individually.
I can always query both the cities and neighborhoods tables individually but the reason why I want to merge the results is for the sole purpose of listing said results alphabetically.
So can someone please show how the UNION query for this would look?
Use:
SELECT c.name
FROM CITIES c
WHERE c.parent_state = 10
UNION ALL
SELECT n.name
FROM NEIGHBORHOODS h
WHERE n.parent_state = 10
UNION ALL will return the result set as a combination of both queries as a single result set. UNION will remove duplicates, and is slower for it - this is why UNION ALL is a better choice, even if it's unlikely to have a city & neighbourhood with the same name. Honestly, doesn't sound like a good idea mixing the two, because a neighbourhood is part of a city...
Something else to be aware of with UNION is that there needs to be the same number of columns in the SELECT clause for all the queries being UNION'd (this goes for UNION and UNION ALL). IE: You'll get an error if the first query has three columns in the SELECT clause and the second query only had two.
Also, the data types have to match -- that means not returning a DATE/TIME data type in the same position was an other query returning an INTEGER.
What you want is probably not a join, but rather, a union. note that a union can only select the exact same columns from both of the joined expressions.
select * from city as c
inner join neighborhoods as n
on n.parent_state = c.parent_state
where c.parent_state=10
You can use Left,Right Join, in case of city and nighborhoods dont have relational data.