This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 4 years ago.
I have a fairly large table of data with multiple years worth of accounts with in it. I'm trying to write a query that will simple pull back the latest year.
However I have tried a number of queries, some from this site that seem to work for other but I can not get it to work on my data set.
The table data looks like so:
So in this example I need to bring back the 2018 year only. The query that I thought might work was:
SELECT *
FROM dbo.Accounts A
INNER JOIN
(SELECT [Account No], MAX(Year) AS MaxYear
FROM dbo.Accounts
GROUP BY [Account No]) MaxYear ON A.[Account No] = MaxYear.[Account No]
AND A.Year = MaxYear.MaxYear
However this still provides me three records on the Max part when I look for the example account number above.
Any help would be much appreciated.
Thanks in advance
PS: The Year datatype is Float and Account No is nvarchar(255)
Then don't group by the account number in the sub-query?
SELECT *
FROM dbo.Accounts A
INNER JOIN
(SELECT MAX(Year) AS MaxYear
FROM dbo.Accounts
) MaxYear
ON A.Year = MaxYear.MaxYear
By grouping by the account number (and then joining on it), you were getting each account's max year, rather than the entire table's max year.
Try below:
SELECT * FROM dbo.Accounts where Year = (Select Max(Year) FROM dbo.Accounts)
you can try like below
SELECT A.*
FROM dbo.Accounts A where A.Year= (select max(year) from dbo.Accounts)
use top
select TOP(1) WITH TIES * from dbo.Accounts
order by Year desc
As I understand year is part of the accountNo column meaning only the first part is the real account number and you want max (last) year per account
SELECT AccountNo, max_year
FROM Accounts
JOIN (SELECT substring(accountno, 1, 6) as accno, max(year) max_year
FROM accounts
group by accno) as max_acc ON max_acc.accno = substring(accountno, 1, 6) AND year = max_year
Related
I have 2 tables and I'm trying to combine them, while removing duplicate entries, I only want to get the last submitted date per month.
unfortunately I was not able to get this working
a.[Region],
a.[Country],
a.[site],
a.[Account Type],
q.[month],
q.[account],
q.[metric],
q.[Goal],
q.[Unit],
q.[Actual],
q.[Waived],
q.[Weight],
q.[Achieved],
q.[SubmittedDateTime]
from [accountTable] a right join [scoreTable] q, (select
max(q.[SubmittedDateTime]) as max_date
group by q.[Month]) on a.[account] = q.[account]
This following script will return you Account/Year/Month wise Last submitted date. I have added Account in consideration as you Joined both table. If only Month wise last submitted is required, I am confused why you need to join tables as Month wise results can be retrieve only from scoreTable!
SELECT a.[account],
YEAR(SubmittedDateTime),
MONTH(SubmittedDateTime),
MAX(SubmittedDateTime)
FROM [accountTable] a
INNER JOIN [scoreTable] q
ON a.[account] = q.[account]
GROUP BY .[account],
YEAR(SubmittedDateTime),
MONTH(SubmittedDateTime)
ORDER BY 1,2,3
You can use row_number() to enumerate the rows within each month and just choose the last one:
select s.*, a.region, a.country, a.site
from (select s.*,
row_number() over (partition by s.account, year(s.submitteddatetime), month(s.submitteddatetime)
order by submitteddatetime desc
) as seqnum
from scoreTable s
) s join
accountTable a
on a.account = s.account
where s.seqnum = 1;
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
I am currently trying to do a query like this:
(Psuedocode)
SELECT
NAME, SUM(VALUE), MONTH
FROM TABLE
WHERE MONTH BETWEEN 12 MONTHS AGO AND NOW
GROUP BY MONTH, NAME
The problem I am getting is that a name exists in a few of the months, but not all of the months, so if i filter this down to return the values for only one name, i sometimes get only 3 or 4 rows, rather than the 12 I expect to see.
My question is, is there a way to return rows, where it will still include the name, and month within the range, where the value would just be set to zero when I am missing the row from the previous result.
My first thought was to just union another select onto it, but I cant seem to get the logic to work to adhere to the group by, as well as the where clauses for limiting the names.
I you have data for all months, you can take the following approach. Generate all the rows (uses a cross join) then bring in the data you want:
select m.month, n.name, sum(t.value)
from (select distinct month from table) m cross join
(select distinct name from table) n left join
table t
on t.month = m.month and t.name = n.name
group by m.month, n.name;
This will return the missing sums as NULL values. If you want zero, then use coalesce(sum(t.value), 0).
you can use something like the following table to generate all the past 12 months as separate rows:
SELECT add_months(trunc(add_months(sysdate, -12), 'MONTH'), LEVEL - 1) AS month_in_range
FROM all_objects
CONNECT BY LEVEL <= 1 + months_between(add_months(sysdate, -12), TRUNC (sysdate, 'MONTH'));
and then do an outer join between you table and this.
I ended up implementing a left outer join similar to #paqogomez 's comment. As my team is already maintaining a time table, its very easy to get the month list for an outer join.
SELECT NAME, SUM(VALUE), TIME.MONTH
FROM (SELECT DISTINCT MONTH FROM TIME_TABLE
WHERE MONTH BETWEEN 12 MONTHS AGO AND NOW) TIME
LEFT OUTER JOIN TABLE ON (TIME.MONTH = TABLE.MONTH)
GROUP BY TIME.MONTH, NAME
I'm trying to write a SQL query in MS ACCESS and I've narrowed it down to the table below, but can't seem to get the last thing right without making several extremely large querys.
Here's the strucuture of thetable I'm trying to query:
The results I want: MemberId and year where memberId had most visits in that year.(That is which memberId had most visits 2014, which had most visits 2015 etc..and I also want the relevant year to be shown in the result)
Thanks!
Sounds like you need to determine MAX(Visits) by year in a subquery, then JOIN to that:
SELECT a.*,b.Max_Visits
FROM YourTable a
JOIN (SELECT Year,MAX(Visits) AS Max_Visits
FROM YourTable
GROUP BY Year
) b
ON a.Year = b.Year
AND a.Visits = b.Max_Visits
If you want to see all members and not just those that had the most visits per year, you can change from JOIN to LEFT JOIN
If there's a tie, this returns both members.
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