0
SELECT "Name""Month","Year","Value" 
from Table
WHERE 
    "Name" LIKE '%JERRY%'
AND "Year" = 
    (SELECT MAX("Year") FROM Table where "Name" LIKE '%JERRY%')
AND "Month"= 
    (SELECT MAX("Month") FROM Table 
     where 
        "Name" LIKE '%JERRY%' 
    AND "Year"= (SELECT MAX("Year") FROM Table where "Name" LIKE '%JERRY%'))

Table -->

Name  | Year | Month | Value
-----------------------------
JERRY   2012    9        100           
JERRY   2012    9        120         
JERRY   2012    9        130           
JERRY   2012    8         20        
JERRY   2011    12        50           

So i want the first three rows as output. As for the latest month for the latest year i need all the values. Can someone suggest a better cleaner query?

Colin 't Hart
  • 7,372
  • 3
  • 28
  • 51
outflanker
  • 445
  • 1
  • 5
  • 19
  • I don't understand your output requirements. Also -- the sample data should presumably contain another person's data rather than just JERRY's? – Transact Charlie Oct 25 '12 at 11:27
  • Can you provide data in a DML like this: – Transact Charlie Oct 25 '12 at 11:28
  • CRATE TABLE #sample ( [Name] VARCHAR(255) , [Year] INT , [Month] INT , [Value] INT ) INSERT #sample ([Name], [Year], [Month], [Value]) VALUES ('JERRY', 2012, 9, 100) , ('JERRY', 2012, 9, 120) , ('JERRY', 2012, 9, 130) , ('JERRY', 2012, 8, 20) , ('JERRY', 2012, 12, 50) SELECT * FROM @sample'code' – Transact Charlie Oct 25 '12 at 11:30

4 Answers4

2
DECLARE @t Table(Name Varchar(30),[Year] Int, [Month] Int,Value Int)
Insert Into @t Values('JERRY' ,  2012,    9,        100 )
Insert Into @t Values('JERRY',   2012,    9 ,       120)         
Insert Into @t Values('JERRY' ,  2012,    9 ,       130)           
Insert Into @t Values('JERRY',   2012 ,   8 ,        20)        
Insert Into @t Values('JERRY',   2011,    12 ,       50) 


Declare @LatestYr Int 
Declare @LatestMonth Int

Select @LatestYr= Max([Year])From @t
Select @LatestMonth = Max([Month]) From @t Where [Year] = @LatestYr

Select * From @t
Where ([Year] = @LatestYr And [Month] = @LatestMonth)

Result

enter image description here

The above query will work just for a single user. And will fail for multiple users, or in case of ties. For example, consider the below scenario

enter image description here

In this case, the needed output will be

enter image description here

So for handling such a situation, I am proposing the below solutions

Solution 1

Select t.* 
From @t t
Join
(
    Select x.Name,x.Max_Year,y.Max_Month
    From
        (   SELECT Name,Max_Year = Max([Year])
            From @t
            Group By Name
        )x
    Join
        (   SELECT Name,[Year],Max_Month= Max([Month])
            From @t
            Group By Name,[Year]
        )y On x.Name = y.Name And x.Max_Year = y.[Year]
)x
On t.Name = x.Name 
And t.[Year] = x.Max_Year 
And t.[Month] = x.Max_Month

OR

Solution 2 (Sql Server 2005+)

Select Name,[Year],[Month],Value
From
(
    Select *,Rn = Rank() Over(Partition By Name Order By [Year] desc, [Month] Desc) 
    From @t
)X Where X.Rn =1

Solution 3 (Sql Server 2005+)

Select Name,[Year],[Month],Value
From
(
    Select *,Rn = Dense_Rank() Over(Partition By Name Order By [Year] desc, [Month] Desc) 
    From @t
)X Where X.Rn =1

The ddl is as under

DECLARE @t Table(Name Varchar(30),[Year] Int, [Month] Int,Value Int)
Insert Into @t Values('JERRY' ,  2012,    9,        100 )
Insert Into @t Values('JERRY',   2012,    9 ,       120)         
Insert Into @t Values('JERRY' ,  2012,    9 ,       130)           
Insert Into @t Values('JERRY',   2012 ,   8 ,        20)        
Insert Into @t Values('JERRY',   2011,    12 ,       50) 
Insert Into @t Values('FERRY' ,  2010,    9,        100 )
Insert Into @t Values('FERRY',   2010,    9 ,       120) 
Insert Into @t Values('FERRY',   2010,    8 ,       120) 
Insert Into @t Values('JERRY1' ,  2012,    9,        100 )
Insert Into @t Values('JERRY1',   2012,    9 ,       120)         
Insert Into @t Values('JERRY1' ,  2012,    9 ,       130)           
Insert Into @t Values('JERRY1',   2012 ,   8 ,        20)        
Insert Into @t Values('JERRY1',   2011,    12 ,       50)

Hope this may help. Thanks

Niladri Biswas
  • 4,153
  • 2
  • 17
  • 24
2

If there are other people in the table then you probably want to use a ranking function: Something like:


DECLARE @sample TABLE (
      [Name] VARCHAR(255)
    , [Year] INT
    , [Month] INT
    , [Value] INT
    )

INSERT @sample ([Name], [Year], [Month], [Value])
VALUES ('JERRY', 2012, 9, 100)           
     , ('JERRY', 2012, 9, 120)
     , ('JERRY', 2012, 9, 130)
     , ('JERRY', 2012, 8, 20)
     , ('JERRY', 2011, 12, 50)
     , ('FRED', 2011, 12, 50)
     , ('FRED', 2011, 12, 120)
     , ('FRED', 2011, 7, 150)

SELECT *
FROM (
    SELECT *
         , RANK() OVER (PARTITION BY [Name] ORDER BY [Year] DESC, [Month] DESC) AS [rnk]
    FROM @sample
    )
    AS samp
WHERE
    samp.[rnk] = 1

Which gives results:

Name                      Year        Month       Value       rnk
------------------------- ----------- ----------- ----------- ------
FRED                      2011        12          50          1
FRED                      2011        12          120         1
JERRY                     2012        9           100         1
JERRY                     2012        9           120         1
JERRY                     2012        9           130         1
Transact Charlie
  • 2,195
  • 17
  • 14
  • 1
    I like your answer but `ORDER BY [Year] * 100 + [Month] DESC` really? Why not `ORDER BY [Year] DESC, [Month] DESC` ? – ypercubeᵀᴹ Oct 25 '12 at 11:44
  • @ypercube, as per OP "So i want the first three rows as output. As for the latest month for the latest year i need all the values. " – Niladri Biswas Oct 25 '12 at 11:56
  • @Niladri: This gives the first rows (latest year,latest month) **per Name**. If the `WHERE "Name" LIKE '%JERRY%'` is included in the internal subquery, the result is exactly what the OP wants. – ypercubeᵀᴹ Oct 25 '12 at 11:58
  • The filtering is done by the `RANK()` function and the `WHERE samp.[rnk] = 1` – ypercubeᵀᴹ Oct 25 '12 at 11:59
  • Yes, I got your point.. you are right..in that case Partition By Name Order By [Year] desc, [Month] Desc is enough – Niladri Biswas Oct 25 '12 at 12:20
1
select * from @t where
[Year] = (select max([year]) from @t) and 
[Month] = (select max([Month]) from @t where [Year]=(select max([year]) from @t))
AnandPhadke
  • 13,160
  • 5
  • 26
  • 33
0
select * 
from    your_table
where   "Name" LIKE '%JERRY%' 
and     year*100+month 

in(
    select top 1 year*100+month 
    from your_table
    where 
    "Name" LIKE '%JERRY%' 
    order by cast(year*100+month as int) desc)


CLICK for demo

user1577417
  • 126
  • 3