SQL query to get max homeruns for each year - sql

In the database we have the table batter, which contains a record for each batter each year they played as well as their game stats for that year. How would I write a query to select each player that has the max number of homeruns out of all players?
I've been trying with
SELECT *
FROM master
WHERE batting.HR = (
SELECT MAX(batting.HR)
FROM batting
)
But have had no luck. How could I do this?

SELECT b.*
FROM batter b
INNER JOIN (
select year, Max(hr) as MaxHR
from batter
group by year
) y on b.year = y.year and b.HR = y.MaxHR
Note this is vulnerable to two players tying. It's not clear what you want to see in that case.

Assuming your RDBMS supports SQL2003, you can use a window function:
SELECT *
FROM
(
SELECT
batter,
year,
hr,
MAX(hr) OVER (PARTITION BY year) AS year_best_hr
FROM batting
)
WHERE hr = year_best_hr

Related

SQL query to sum a column prior to date and show all entries after that date

I have a table where limits were sanctioned to the customer
I am trying to get the output as below picture i.e. total amount sanctioned till particular date
I am trying below code but this sums the total sanction amount
select gam.id, sum(SANCTION_AMOUNT) from gam
join (select ID,ACCOUNT_OPEN_DATE from gam where ACCOUNT_OPEN_DATE between'01-04-2019' and '30-04-2019' AND SCHEME_CODE IN ('SB','CCKLY')) ) action
on( gam.ACCOUNT_OPEN_DATE <=action.ACCOUNT_OPEN_DATE and gam.id=action.cust_id) group by gam.id;
In Oracle, this can be a way:
select id, sanction_amount, scheme_code, account_open_date,
sum(sanction_amount) over (partition BY ID order by account_open_date) as total_sanction_amount
from gam
order by account_open_date
Not sure your database is MySQL or Oracle, But this below script is workable in most of the database. Just adjust the table and column names accordingly.
You can check MySQL DEMO HERE
SELECT *,
(
SELECT SUM(sanction_Amount)
FROM Your_Table B
WHERE B.ID = A.ID
AND B.acc_open_date <= A.acc_open_date
) Total_sanction_Amount
FROM Your_Table A

Selecting the max value of two different columns

I have the following table named 'MoviesInStock'
I would like to select to latest movies from the last month.
In this case, the result should be only the movie 'The Mummy' since he is latest one.
I was trying the next query:
SELECT MovieName
FROM MovieInStock
WHERE Month = (SELECT MAX(Month) FROM MovieInStock) AND
(SELECT MovieName FROM MovieInStock WHERE Year = (SELECT MAX(Year) FROM MovieInStock))
But choosing the AND operator was not that smart. I was also trying to create a temporary table using SELECT INTO # for selecting the Max Year and then on the temp table to select the Max Month, but then it become complicated to me.
You are overcomplicating the problem. You can use TOP with ORDER BY.
Because you say "movies":
select top (1) with ties mis.*
from movieinstock mis
order by year desc, month desc
other solution, but better is Gordon Solution
with maxdt as (
select MAX(Month) MaxMonth, MAX(Year) MaxYear FROM MovieInStock
)
SELECT top 1 MovieName
FROM MovieInStock f1
inner join maxdt f2 on f1.Month=f2.MaxMonth and f1.Year=MaxYear

Pulling max values grouped by a variable with other columns in SQL

Say I have three columns in a very large table: a timestamp variable (last_time_started), a player name (Michael Jordan), and the team he was on the last time he started (Washington Wizards, Chicago Bulls), how do I pull the last time a player started, grouped by player, showing the team? For example:
if I did
select max(last_time_started), player, team
from table
group by 2
I would not know which team the player was on when he played his last game, which is important to me.
In Postgres the most efficient way is to use distinct on():
SELECT DISTINCT ON (player)
last_time_started,
player,
team,
FROM the_table
ORDER BY player, last_time_started DESC;
Using a window function is usually the second fastest solution, using a join with a derived table is usually the slowest alternative.
Here's a couple of ways to do this in Postgres:
With windowing functions:
SELECT last_time_started, player, team
FROM
(
SELECT
last_time_started,
player,
team,
CASE WHEN max(last_time_started) OVER (PARTITION BY PLAYER) = last_time_started then 'X' END as max_last_time_started
FROM table
)
WHERE max_last_time_started = 'x';
Or with a correlated subquery:
SELECT last_time_started, player, team
FROM table t1
WHERE last_time_started = (SELECT max(last_time_started) FROM table WHERE table.player = t1.player);
Try this solution
select s.*
from table s
inner join (
select max(t.last_time_started) as last_time_started, t.player
from table t
group by t.player) v on s.player = t.player and s.last_time_started = t.last_time_started
Also this approach should be faster, because it does not contain join
select v.last_time_started,
v.player,
v.team
from (
select t.last_time_started,
t.player,
t.team,
row_number() over (partition by t.player order by last_time_started desc) as n
from table t
) v
where v.n = 1

2.5 percent increase of previous field?

I have a table with a series of IDs. Each ID has dates ranging up to year 2025 from current year. Each year for each ID has a specific price.
http://i.imgur.com/srplSDo.jpg
Once I get to a certain point with each ID, it no longer has a specific price. So what I am wanting to do is take the previous years price and increase it by 2.5 percent. I have figured a way to grab the previous years price with this
SELECT a.*,
(CASE
WHEN a.YEARLY_PRICING is not null
THEN a.YEARLY_PRICING
ELSE (SELECT b.YEARLY_PRICING
FROM #STEP3 b
WHERE (a.id = b.id) AND (b.YEAR = a.YEAR-1))*1.025
END) AS TEST
FROM #STEP3 a
which would provide these results:
http://imgur.com/MJutM99
but the problem I am having is after the first null year, it is still recognizing the previous yearly_pricing as null, which gives me the null results, so obviously this method won't work for me. Any other suggestions for improvement?
Thanks
WITH CTE AS
(
SELECT ID, Year, Price, Price AS Prev
FROM T A
WHERE Year = (SELECT min(year) FROM T WHERE T.ID = A.ID GROUP BY T.ID)
UNION ALL
SELECT T.ID, T.Year, T.Price, ISNULL(T.Price, 1.025*Prev)
FROM T JOIN CTE ON T.ID = CTE.ID
AND T.Year - 1 = CTE.YEAR
)
SELECT * FROM CTE
ORDER BY ID, Year
SQL Fiddle Demo
What you want is a way to find not just the previous year (year - 1), but instead the year that is previous and also has a not-null price. To query for such a year (without solving your problem), you would do something like this:
select a.*
, (select max(year)
from step3 b
where a.id=b.id and a.year>b.year and b.yearly_pricing is not null
) PRIOR_YEAR
from step3 a
Since SQL-Server allows common-table expressions, you can call the above query "TMP", and then approach it this way. The CALC_PRICE in any year will be the price from the "PRIOR_YEAR" found as per the above query, multiplied by factor. That factor will be 1.025 to the POWER of the number of years from "PRIOR_YEAR" to the current year.
You would end up with SQL like this:
with TMP AS (
select a.*
, (select max(year)
from step3 b
where a.id=b.id and a.year>b.year and b.yearly_pricing is not null
) PRIOR_YEAR
from step3 a
)
select t.*,
c.yearly_pricing As prior_price,
c.yearly_pricing * POWER(1.025 , (t.year-t.prior_year)) calc_price
from tmp t
left join step3 c
on t.id=c.id and t.prior_year = c.year
It still has nulls, etc. but those are easily handled with COALESCE() or CASE expressions like you had in your question.
Here's an SQL Fiddle which shows how it works: http://sqlfiddle.com/#!3/296a4/21

SQL query to select distinct row with minimum value

I want an SQL statement to get the row with a minimum value.
Consider this table:
id game point
1 x 5
1 z 4
2 y 6
3 x 2
3 y 5
3 z 8
How do I select the ids that have the minimum value in the point column, grouped by game? Like the following:
id game point
1 z 4
2 y 5
3 x 2
Use:
SELECT tbl.*
FROM TableName tbl
INNER JOIN
(
SELECT Id, MIN(Point) MinPoint
FROM TableName
GROUP BY Id
) tbl1
ON tbl1.id = tbl.id
WHERE tbl1.MinPoint = tbl.Point
This is another way of doing the same thing, which would allow you to do interesting things like select the top 5 winning games, etc.
SELECT *
FROM
(
SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Point) as RowNum, *
FROM Table
) X
WHERE RowNum = 1
You can now correctly get the actual row that was identified as the one with the lowest score and you can modify the ordering function to use multiple criteria, such as "Show me the earliest game which had the smallest score", etc.
This will work
select * from table
where (id,point) IN (select id,min(point) from table group by id);
As this is tagged with sql only, the following is using ANSI SQL and a window function:
select id, game, point
from (
select id, game, point,
row_number() over (partition by game order by point) as rn
from games
) t
where rn = 1;
Ken Clark's answer didn't work in my case. It might not work in yours either. If not, try this:
SELECT *
from table T
INNER JOIN
(
select id, MIN(point) MinPoint
from table T
group by AccountId
) NewT on T.id = NewT.id and T.point = NewT.MinPoint
ORDER BY game desc
SELECT DISTINCT
FIRST_VALUE(ID) OVER (Partition by Game ORDER BY Point) AS ID,
Game,
FIRST_VALUE(Point) OVER (Partition by Game ORDER BY Point) AS Point
FROM #T
SELECT * from room
INNER JOIN
(
select DISTINCT hotelNo, MIN(price) MinPrice
from room
Group by hotelNo
) NewT
on room.hotelNo = NewT.hotelNo and room.price = NewT.MinPrice;
This alternative approach uses SQL Server's OUTER APPLY clause. This way, it
creates the distinct list of games, and
fetches and outputs the record with the lowest point number for that game.
The OUTER APPLY clause can be imagined as a LEFT JOIN, but with the advantage that you can use values of the main query as parameters in the subquery (here: game).
SELECT colMinPointID
FROM (
SELECT game
FROM table
GROUP BY game
) As rstOuter
OUTER APPLY (
SELECT TOP 1 id As colMinPointID
FROM table As rstInner
WHERE rstInner.game = rstOuter.game
ORDER BY points
) AS rstMinPoints
This is portable - at least between ORACLE and PostgreSQL:
select t.* from table t
where not exists(select 1 from table ti where ti.attr > t.attr);
Most of the answers use an inner query. I am wondering why the following isn't suggested.
select
*
from
table
order by
point
fetch next 1 row only // ... or the appropriate syntax for the particular DB
This query is very simple to write with JPAQueryFactory (a Java Query DSL class).
return new JPAQueryFactory(manager).
selectFrom(QTable.table).
setLockMode(LockModeType.OPTIMISTIC).
orderBy(QTable.table.point.asc()).
fetchFirst();
Try:
select id, game, min(point) from t
group by id