GROUP BY expression (part of column) instead of whole column - sql

I'm creating a query:
I need to get the quantity of returns made for each year.
ReturnDate is the specific date each member has, when the return was made.
To get the year I'm using LEFT(ReturnDate,4).
It all seem OK so far, but I need the list to show Year, City and the complete number of returns for that city, like:
YEAR CITY QUANTITY
2011 London 300
2011 Stockholm 40
2012 London 250
Now, I'm not getting:
YEAR CITY QUANTITY
2011 London 200
2011 London 100
2011 Stockholm 30
2011 Stockholm 10
2012 London 250
This is what I've come up with so far:
SELECT LEFT(ReturnDate,4) AS Year, City, COUNT(ReturnDate) AS Quantity
FROM Member
GROUP BY ReturnDate, City

Try:
GROUP BY LEFT(ReturnDate, 4), City

Alternatively, you can try using DATEPART:
SELECT DATEPART(yyyy, ReturnDate) AS Year, City, COUNT(ReturnDate) AS Quantity
FROM Member
GROUP BY DATEPART(yyyy, ReturnDate), City

Related

find out the player with highest score in each year

I have a table like these
country
gender
player
score
year
Germany
male
Michael
14
1990
Austria
male
Simon
13
1990
Germany
female
Mila
16
1990
Austria
female
Simona
15
1990
This is a table in the database. It shows 70 countries around the world with player names and gender. It shows which player score how many goals in which year. The years goes from 1990 to 2015. So the table is large. Now I would like to know which female player and which male player score most in every year from 2010 to 2012.
I expect this:
gender
player
score
year
male
Michael
24
2010
male
Simon
19
2011
male
Milos
19
2012
female
Mara
16
2010
female
Simona
16
2011
female
Dania
17
2012
I used that code but got an error
SELECT gender,year,player, max(score) as score from (football) where player = max(score) and year in ('2010','2011','2012') group by 1,2,3
football is the table name
with main as (
select
gender,
player,
year,
sum(score) as total_score -- incase each player played multiple match in a year
from <table_name>
where year between 2010 and 2012
group by 1,2,3
),
ranking as (
select *,
row_number(total_score) over(partition by year, gender order by total_score desc) as rank_
)
select
gender,
player,
year,
total_score
from ranking where rank_ = 1
filter on years
first you add total score, to make sure you cover the cases if there are multiple matches played by the same player in same year
then you create a rank based on year, gender and the total score, so for a given year and for a given gender create a rank
then you filter on rank_ = 1 as it represents the highest score
You can use the dense_rank function to achieve this, if you are using sqlite version 3.25 or higher.
Query
select t.* from(
select *, dense_rank() over(
partition by year, gender
order by score desc
) as rn
from football
where year in ('2010','2011','2012')
) as t
where t.rn = 1;

How to write a correct SQL query?

I have a table with following columns:
city name, population, year (year is when the data about population was collected)
In the table there can be the same city for more than 1 year, for example:
New York 7999999 2019
New York 8000000 2020
New York 7999998 2018
London 7000000 2020
London 7000000 2016
Moscow 12000000 2017
(So there're 3 records about New York, 2 about London and 1 about Moscow)
I need a query to get the newest records about every city.
So here the result will be:
New York 8000000 2020
London 7000000 2020
Moscow 12000000 2017
You want the latest record per city. A cross-database solution that usually performs well is to filter with a correlated subquery:
select t.*
from mytable t
where t.year = (select max(t1.year) from mytable t1 where t1.town = t.town)
A multi-column index on (town, year) would speed up this query.
you can use something like this:
SELECT town, amount, date FROM townlist
WHERE date IN (SELECT max(date) FROM townlist)
In general you need a solution to group the list by town - with the newest entry on top: another approach
SELECT town, amount, date
FROM (SELECT * FROM townlist ORDER BY date DESC) as sortedTable
GROUP BY town

SQL Columns Grouping

I have an SQL View Name dbo.financialactuals
ACCTNAME Month Balance Acctctgry Year Description
sales 1 344.78 income 2018 revenueAX
sales 2 2744.78 income 2018 ProduceAX
sales 3 8745.78 income 2018 annualAx
INTEREST INC 1 7866 Interest 2018 ProduceAX
INTEREST INC 2 766 Interest 2018 CTGAX3
sales 5 744.78 other 2018 AX
I tried to sum balance by AcctName But it still showing the same result. I think it's because of the description column. So, I removed the description from the select statement but it's acting same.
SELECT AcctName,
SUM(Balance) AS Balance,
AcctCtrgry,
Year,
FROM dbo.financialactuals
GROUP BY AcctName, Acctctrgy, Year,
I need an output like this.
AcctNAme Balance AcctCtrgy Year
sales -3089.56 income 2018
INTEREST INC 9632 InterestINC 2018
As it was said already in the comments this should give the requested result.
SELECT AcctName,
SUM(Balance) AS Balance,
AcctCtrgry,
Year,
FROM dbo.financialactuals
GROUP BY AcctName, Acctctrgy, Year
But the sum on the sales will be -11835.34 not -3089.56.

How to group two fields together in SQL?

say I have a sql that currently returns all soccer players who has played during each years. Like so:
name year goals
john 2010 1
john 2006 2
john 2006 8
fred 2006 1
But I want the result to be grouped by the years they played, but do not compress player names if they are from different years, like so:
name year goals
john 2010 1
john 2006 10 <--- This is compressed, but there are still 2 johns
fred 2006 1 since they are from different years
say I have done this so far.
(select name, year, goals
from table) as T
If I just do
select *
from
(select name, year, goals
from table) as T
group by year;
Fred will disappear, but if I do "group by name", there are only 1 john left. Any help?
select name, year, sum(goals) as totalgoals
from table
group by name, year

aggregate a few rows and display in oracle

I have a table ZXC
select NAME, MONTH, YEAR, DEPT, MONTHVAL, YEARVAL from ZXC
the column MONTHVAL has some values. I want to aggregate some rows based on the combination of name, dept and month, and display the aggregated value in YEARVAL column.
for example, if i have the table
Name Month Year Dept Monthval Yearval
BLAKE Jan 2011 100 124.542 0
KING Feb 2011 200 234.542 0
KING Jan 2011 200 27764.464 0
BLAKE March 2011 100 0 0
BLAKE Feb 2011 400 0 0
SCOTT Jan 2011 500 24564.464 0
KING March 2011 200 1265.542 0
KING April 2011 200 1065.542 0
then i want to see the result as
Name Month Year Dept Monthval Yearval
BLAKE Jan 2011 100 124.542 124.542
KING Jan 2011 200 27764.464 27764.464
SCOTT Jan 2011 500 24564.464 24564.464
KING Feb 2011 200 234.542 27999.006
BLAKE Feb 2011 100 0 124.542
KING March 2011 200 1265.542 29264.548
BLAKE March 2011 100 0 124.542
KING April 2011 200 1065.542 30330.09
What about this:
SELECT name
, dept
, year
, SUM( monthval ) yearval
FROM zxc
GROUP BY name
, dept
, year;
This would produce a total of monthly values for each year. I am not really sure if this is
what you needed, but looks like it to me.
You can make it even fancier by using ROLLUP() or CUBE() functions in GROUP BY functions (multiple level of aggregations).
Sounds like:
select NAME,
MONTH,
YEAR,
DEPT,
MONTHVAL,
SUM(MONTHVAL) OVER (PARTITION BY YEAR) YEARVAL
from ZXC
Based on your output, it seems like you want a running total for every person. Basically, the following query shows a general solution for this:
SELECT
Name,
Month,
Year,
Dept,
Monthval,
SUM(Monthval) OVER (PARTITION BY Name, Dept ORDER BY Year, Month) AS Yearval
FROM ZXC
But there might be a problem with ordering by Month, because the months seems to be stored as names in your table, not as numbers. I would then change the above like this:
SELECT
Name,
Month,
Year,
Dept,
Monthval,
SUM(Monthval) OVER (
PARTITION BY Name, Dept
ORDER BY TO_DATE(Year || '-' || SUBSTR(Month, 1, 3), '-01', 'YYYY-MON-DD')
) AS Yearval
FROM ZXC