Unable to use nonequi join(<=) in hive - hive

I am new to hive and was trying to execute an query which contains nonequi join.
But when I try to execute in hive 0.7 I am getting error due to nonequi join condition.
Query:
SELECT * INTO dbo.tbl_B
FROM ( select
Id,
Name,
Age,
SellingPrice,
row_number() OVER ( PARTITION BY Id,Name
ORDER BY Age asc) AS row_no
from tbl_A
LEFT JOIN dbo.tbl_C
ON A.[Id]=C.[Id]
and A.SellingPrice <= C.BuyingPrice
) AA
WHERE row_no = 1 ;
Please provide me idea to rewrite this query without using nonequi join.

Move non-equi join condition to the where clause:
SELECT *
FROM ( select
Id,
Name,
Age,
SellingPrice,
row_number() OVER ( PARTITION BY Id,Name ORDER BY Age asc) AS row_no
from tbl_A
LEFT JOIN dbo.tbl_C
ON A.[Id]=C.[Id]
where (A.SellingPrice <= C.BuyingPrice) OR (C.BuyingPrice is null)
) AA
WHERE row_no = 1 ;
OR (C.BuyingPrice is null) is necessary to allow left join, without this condition, left join will be transformed to inner join because non-equality condition alone as is will filter out nulls, see here.

Solution not working for me
query used:
CREATE TABLE IMART_PREP.TST (STRT_DT DATE , END_DT DATE, ID INT , SALARY INT );
INSERT INTO IMART_PREP.TST VALUES ( '2018-01-01' , '2018-01-31' ,1, 1000);
INSERT INTO IMART_PREP.TST VALUES ( '2018-02-01' , '2018-02-28' , 1, 2000);
INSERT INTO IMART_PREP.TST VALUES ( '2018-03-01' , '2018-03-30' , 1, 3000);
INSERT INTO IMART_PREP.TST VALUES ( '2018-04-01' , '2018-04-30' , 1, 4000);
SELECT * FROM IMART_PREP.TST;
CREATE TABLE IMART_PREP.TST_1 (STRT_DT DATE , END_DT DATE, ID INT , SALARY INT );
INSERT INTO IMART_PREP.TST_1 VALUES ( '2018-01-01' , '2018-01-31', 1, 1000);
SELECT *
FROM IMART_PREP.TST A , IMART_PREP.TST_1 B
WHERE ( (A.ID = B.ID ) AND (A.STRT_DT BETWEEN B.STRT_DT AND B.END_DT ) ) OR (B.STRT_DT IS NULL );

Related

Group by with gap in date sequence ("gaps and islands")

I am trying to solve a "gaps and islands" by date issue I'm facing (kudos to Gordon Linoff helping me identify this issue). I want to group the below table by person, office and job while respecting order by person,from_date. consider the table below:
declare #temp table(person varchar(25),office varchar(25),job varchar(25),from_date date,to_date date)
insert into #temp values ('jon','ny','programmer','1/1/2020','1/3/2020');
insert into #temp values ('jon','ny','programmer','1/4/2020','1/5/2020');
insert into #temp values ('jon','dc','programmer','1/6/2020','1/7/2020');
insert into #temp values ('jon','ny','programmer','1/8/2020','1/9/2020');
insert into #temp values ('lou','ny','programmer','1/1/2020','1/3/2020');
insert into #temp values ('lou','ny','programmer','1/4/2020','1/5/2020');
insert into #temp values ('lou','dc','programmer','1/6/2020','1/7/2020');
insert into #temp values ('lou','ny','programmer','1/8/2020','1/9/2020');
the intended output is
This is a type of gaps-and-islands problem. If there are no gaps in the dates, the simplest solution is the difference of row numbers:
select person, office, job, min(from_date), max(to_date)
from (select t.*,
row_number() over (partition by person, office, job order by from_date) as seqnum,
row_number() over (partition by person, office order by from_date) as seqnum_2
from t
) t
group by person, office, job, (seqnum - seqnum_2)
This is a general solution:
WITH preceders_and_followers AS (
SELECT
b.person,
b.office,
b.job,
b.from_date,
b.to_date,
CASE
WHEN EXISTS (
SELECT
c.*
FROM
ora$ptt_tmp c
WHERE
b.person = c.person
AND b.office = c.office
AND b.job = c.job
AND ( b.from_date - 1 BETWEEN c.from_date AND c.to_date )
) THEN
1
END AS has_preceder,
CASE
WHEN EXISTS (
SELECT
c.*
FROM
ora$ptt_tmp c
WHERE
b.person = c.person
AND b.office = c.office
AND b.job = c.job
AND ( b.to_date + 1 BETWEEN c.from_date AND c.to_date )
) THEN
1
END AS has_follower
FROM
ora$ptt_tmp b
ORDER BY
1,
2,
3
)
SELECT DISTINCT
pf1.person,
pf1.office,
pf1.job,
pf1.from_date,
(
SELECT
MIN(pf2.to_date)
FROM
preceders_and_followers pf2
WHERE
pf1.person = pf2.person
AND pf1.office = pf2.office
AND pf1.job = pf2.job
AND pf2.to_date >= pf1.from_date
AND has_follower IS NULL
) to_date
FROM
preceders_and_followers pf1
WHERE
pf1.has_preceder IS NULL
ORDER BY
1,
4,
2,
3;

How can I transform my N little queries into one query?

I have a query that gives me the first available value for a given date and pair.
SELECT
TOP 1 value
FROM
my_table
WHERE
date >= 'myinputdate'
AND key = 'myinpukey'
ORDER BY date
I have N pairs of key and dates, and I try to find out how not to query each pair one by one. The table is rather big, and N as well, so it's currently heavy and slow.
How can I query all the pairs in one query ?
A solution is to use APPLY like a "function" created on the fly with one or many columns from another set:
DECLARE #inputs TABLE (
myinputdate DATE,
myinputkey INT)
INSERT INTO #inputs(
myinputdate,
myinputkey)
VALUES
('2019-06-05', 1),
('2019-06-01', 2)
SELECT
I.myinputdate,
I.myinputkey,
R.value
FROM
#inputs AS I
CROSS APPLY (
SELECT TOP 1
T.value
FROM
my_table AS T
WHERE
T.date >= I.myinputdate AND
T.key = I.myinputkey
ORDER BY
T.date ) AS R
You can use OUTER APPLY if you want NULL result values to be shown also. This supports fetching multiple columns and using ORDER BY with TOP to control amount of rows.
This solution is without variables. You control your N by setting the right value to the row_num predicate.
There are plenty of ways how to do you what you want and it all depends on your specific needs. As it answered already, that you can use temp/variable table to store these conditions and then join it on the same conditions you use predicates. You can also create user defined data type and use it as param to the function/procedure. You might use CROSS APPLY + VALUES clause to get that list and then join it.
DROP TABLE IF EXISTS #temp;
CREATE TABLE #temp ( d DATE, k VARCHAR(100) );
GO
INSERT INTO #temp
VALUES ( '20180101', 'a' ),
( '20180102', 'b' ),
( '20180103', 'c' ),
( '20180104', 'd' ),
( '20190101', 'a' ),
( '20190102', 'b' ),
( '20180402', 'c' ),
( '20190103', 'c' ),
( '20190104', 'd' );
SELECT a.d ,
a.k
FROM ( SELECT d ,
k ,
ROW_NUMBER() OVER ( PARTITION BY k ORDER BY d DESC ) row_num
FROM #temp
WHERE (d >= '20180401'
AND k = 'a')
OR (d > '20180401'
AND k = 'b')
OR (d > '20180401'
AND k = 'c')
) a
WHERE a.row_num <= 1;
-- VALUES way
SELECT a.d ,
a.k
FROM ( SELECT t.d ,
t.k ,
ROW_NUMBER() OVER ( PARTITION BY t.k ORDER BY t.d DESC ) row_num
FROM #temp t
CROSS APPLY (VALUES('20180401','a'), ('20180401', 'b'), ('20180401', 'c')) f(d,k)
WHERE t.d >= f.d AND f.k = t.k
) a
WHERE a.row_num <= 1;
If all the keys are using the same date, then use window functions:
SELECT key, value
FROM (SELECT t.*, ROW_NUMBER() OVER (PARTITION BY key ORDER BY date) as seqnum
FROM my_table t
WHERE date >= #input_date AND
key IN ( . . . )
) t
WHERE seqnum = 1;
SELECT key, date,value
FROM (SELECT ROW_NUMBER() OVER (PARTITION BY key,date ORDER BY date) as rownum,key,date,value
FROM my_table
WHERE
date >= 'myinputdate'
) as d
WHERE d.rownum = 1;

SQL aggregation of data based on dates

I am sure this is a very stupid question and I am having a dumb moment.
Consider the following basic scenario (this is a very small scenario compared with reality which has many many dimensions and measures):
What I need to get to is the expected output.
So ALL costs between the input_Date and output_date defined in the params are included. However only the latest PID is included- defined as either:
1- where PIDs run sequentially, or overlap the latest one based on date_to as long as both aren't active at the # output date
2- where there are two PID active at the # output date show both
I can't for the life of me work out how to do this in SQL, note that is has to be non dynamic and not use any CTE unfortunately, just your basic SQL with subqueries
Obviously returning the necessary list of ID and PID is easy:
declare #input_date date ='2006-01-01'
declare #output_date date ='2006-12-31'
select a.PID, a.ID
from #tmp a
where date_from <=#output_date and date_to >=#input_date
But I can't figure out how to join this back to return the correct cost values
drop table tmp
CREATE TABLE [dbo].[tmp](
[date_from] [datetime] NOT NULL,
[date_to] [datetime] NOT NULL,
[ID] [nvarchar](25) NOT NULL,
[PID] [nvarchar](25) NOT NULL,
[cost] [float] NULL
) ON [PRIMARY]
INSERT tmp VALUES('2005-1-1','2005-1-31','10001','X123',1254.32)
INSERT tmp VALUES('2000-10-10','2006-8-21','10005','TEST01',21350.9636378758)
INSERT tmp VALUES('2006-8-22','2099-12-31','10005','TEST02',22593.4926163943)
INSERT tmp VALUES('2006-1-1','2099-12-31','10006','X01',22458.3342354444)
INSERT tmp VALUES('2006-2-8','2099-12-31','10006','X02',22480.3772331959)
INSERT tmp VALUES('2006-1-1','2006-2-7','10007','AB01',565.416874152212)
INSERT tmp VALUES('2006-2-8','2006-7-31','10007','AA05',19108.3206482165)
I've made some progress using a CTE so you can see how I would do it this way if I could:
drop table #tmp
CREATE TABLE #tmp (
[date_from] [datetime] NOT NULL,
[date_to] [datetime] NOT NULL,
[ID] [nvarchar](25) NOT NULL,
[PID] [nvarchar](25) NOT NULL,
[cost] [float] NULL
) ON [PRIMARY]
INSERT #tmp VALUES('2005-1-1','2005-1-31','10001','X123',1254.32)
INSERT #tmp VALUES('2000-10-10','2006-8-21','10005','TEST01',21350.9636378758)
INSERT #tmp VALUES('2006-8-22','2099-12-31','10005','TEST02',22593.4926163943)
INSERT #tmp VALUES('2006-1-1','2099-12-31','10006','X01',22458.3342354444)
INSERT #tmp VALUES('2006-2-8','2099-12-31','10006','X02',22480.3772331959)
INSERT #tmp VALUES('2006-1-1','2006-2-7','10007','AB01',565.416874152212)
INSERT #tmp VALUES('2006-2-8','2006-7-31','10007','AA05',19108.3206482165)
declare #input_date date ='2006-01-01'
declare #output_date date ='2006-12-31'
;with cte as (
select t.id,t.PID,t.cost,t.date_from,t.date_to ,
iif(date_To >= #output_date OR max_date_To is not null,PID,NULL) as PID2,
b.total_id_cost
from #tmp t
left join (select ID,max(date_to) as max_date_to
from #tmp
where date_from <=#output_date and date_to >=#input_date
group by ID) a
on t.ID = a.ID and t.date_to = a.max_date_to
left join (Select ID, sum(cost) as total_id_cost
from #tmp
where date_from <=#output_date and date_to >=#input_date
group by ID) b
on t.ID = b.ID
where date_from <=#output_date and date_to >=#input_date )
select distinct ID,PID2,
iif(ID in (
select ID
from cte
where PID2 IS NULL)
and ID not in (select ID
from cte
where PID IS NOT NULL
group by ID
having count (distinct PID2) >1 ), cte.total_id_cost, cost) as cost
from cte
where PID2 is not null;
so it looks like there's several problems to solve within 1 query.
We want the PID that matches the latest date. This wasn't too difficult and can be solved by joining the data with an aggregate of itself that finds the latest date
Where both PID is active i.e. overlapping from and to dates, then both must show. I found this to be more tricky. in the end I did a query to find the ones that do overlap and meet the dates, and did a count on that. then used this count as a criteria for the join on 1. so that it can conditionally pick the PID that matches the latest date
Then finally using the results from above, you can do the sum to get the cost. The resulting query is a bit of a monster, but here it is.
if it doesn't cover other scenarios not detailed, do let me know.
DECLARE #Data TABLE (date_from DATETIME, date_to DATETIME, ID INT, PID NVARCHAR(50), COST MONEY)
INSERT #Data VALUES('2005-1-1','2005-1-31','10001','X123',1254.32)
INSERT #Data VALUES('2000-10-10','2006-8-21','10005','TEST01',21350.9636378758)
INSERT #Data VALUES('2006-8-22','2099-12-31','10005','TEST02',22593.4926163943)
INSERT #Data VALUES('2006-1-1','2099-12-31','10006','X01',22458.3342354444)
INSERT #Data VALUES('2006-2-8','2099-12-31','10006','X02',22480.3772331959)
INSERT #Data VALUES('2006-1-1','2006-2-7','10007','AB01',565.416874152212)
INSERT #Data VALUES('2006-2-8','2006-7-31','10007','AA05',19108.3206482165)
declare #input_date date ='2006-01-01'
declare #output_date date ='2006-12-31'
select
a.ID,
PIDForMaxDateThatMatches.PID,
SUM(a.cost) as cost
from
#Data a
inner join (
-- number of PIDs for dates that overlap grouped by ID
select
a.ID,
-- where there's no overlap then we want the count to be 1 so that later we can use it as condition
COUNT(DISTINCT ISNULL(b.PID,'')) as NumberOfPID
from
#Data a
-- may or may not find overlaps
LEFT JOIN #data b ON
b.date_from <=#output_date and
b.date_to >=#input_date and
a.date_from <= b.date_to and
a.date_to >= b.date_from and
a.ID = b.ID and
a.PID <> b.PID
where
a.date_from <=#output_date and
a.date_to >=#input_date
group by
a.ID) as PIDCountForOverlappingMatches ON
a.ID = PIDCountForOverlappingMatches.ID
left join (
-- get the PID that matches the max date_to
select
DataForMaxDate.ID,
DataForMaxDate.date_from,
DataForMaxDate.date_to,
DataForMaxDate.PID
from
#Data as DataForMaxDate
inner join (
-- get the max date_to that matches the criteria
select
ID,
MAX(date_to) as maxDateTo
from
#Data a
where
date_from <=#output_date and
date_to >=#input_date
group by
ID) as MaxToDatePerID on
DataForMaxDate.ID = MaxToDatePerID.ID and
DataForMaxDate.date_to = MaxToDatePerID.maxDateTo) as PIDForMaxDateThatMatches on
a.ID = PIDForMaxDateThatMatches.ID AND
-- if there's no overlapping dates the PID count would be 1, which we'll take the PID that matches the max(date_to)
-- but if there is overlap, then we want both dates to show, thus the from date must also match before we take the PID
(PIDCountForOverlappingMatches.NumberOfPID = 1 OR a.date_from = PIDForMaxDateThatMatches.date_from)
where
a.date_from <= #output_date and
a.date_to >= #input_date
GROUP BY
a.ID,
PIDForMaxDateThatMatches.PID
ORDER BY
a.ID
EDIT: DB Fiddle http://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=d43cb4b9765da1bca035531e78a2c77d
Results:
ID PID cost
10005 TEST02 43944.4562
10006 X01 22458.3342
10006 X02 22480.3772
10007 AA05 19673.7375
Hello you can try the following query :
select a.resource_id ID, max(a.post_id) PID, SUM(a.cost) Cost
from #tmp a
where date_from <=#output_date and date_to >=#input_date
group by a.resource_id
order by a.resource_id;
I think this might work:
SELECT
t1.ID,
q1.PID,
SUM(t1.cost)
FROM
Table AS t1
JOIN
(
SELECT
q2.ID,
t2.PID
FROM
(
SELECT
ID,
MAX(date_to) AS maxdate
FROM
Table
GROUP BY
ID
) AS q2
JOIN
table AS t2
ON
q2.ID = t2.ID
AND
q2.maxdate = t2.date_to
) AS q1
ON
t1.ID = q1.ID
AND
t1.PID = q1.PID
GROUP BY
t1.ID,
q1.PID
Here is a query without CTE. Idea of query:
1) Find consecutive dates and make different groups within each id
2) Find min and max date, sum of costs for each group
3) Limit by input parametres
declare #date_from date = '20060101'
declare #date_to date = '20061231'
declare #myTable table(
date_from date
, date_to date
, id int
, pid varchar(30)
, cost decimal(10,2)
)
insert into #myTable values
('20050101', '20050201', 10001, 'x123', 1254.32)
, ('20001010', '20060821', 10005, 'test01', 21350.96)
, ('20060822', '20991231', 10005, 'test02', 22593.49)
, ('20060101', '20991231', 10006, 'x01', 22548.33)
, ('20060208', '20991231', 10006, 'x02', 22480.38)
, ('20060101', '20060207', 10007, 'abo1', 565.42)
, ('20060208', '20060731', 10007, 'abo2', 19108.32)
select
date_from = min(date_from), date_to = max(date_to)
, id, pid = max(case when date_to = max_date_to then pid end)
, cost = sum(cost)
from (
select
a.date_from, a.date_to, a.id, a.pid, a.cost, a.rn, grp = sum(b.ss)
, max_date_to = max(a.date_to) over (partition by a.id, sum(b.ss))
from
(
select
a.*, ss = case when datediff(dd, b.date_to, a.date_from) = 1 then 0 else 1 end
from
(
select
*, rn = row_number() over (partition by id order by date_from)
from
#myTable
) a
left join (
select
*, rn = row_number() over (partition by id order by date_from)
from
#myTable
) b on a.id = b.id and a.rn - 1 = b.rn
) a
left join (
select
a.*, ss = case when datediff(dd, b.date_to, a.date_from) = 1 then 0 else 1 end
from
(
select
*, rn = row_number() over (partition by id order by date_from)
from
#myTable
) a
left join (
select
*, rn = row_number() over (partition by id order by date_from)
from
#myTable
) b on a.id = b.id and a.rn - 1 = b.rn
) b on a.id = b.id and a.rn >= b.rn
group by a.date_from, a.date_to, a.id, a.pid, a.cost, a.rn
) t
group by id, grp, max_date_to
having min(date_from) <= #date_from and max(date_to) >= #date_to
order by id
Output
date_from date_to id pid cost
------------------------------------------------
2000-10-10 2099-12-31 10005 test02 43944.45
2006-01-01 2099-12-31 10006 x01 22548.33
Result is a bit different than your provided output. But:
1) For id = 10006 and pid = X02 date_from = 08/02/2006 while input is 01/01/2006
2) For id = 10007 date_to = 31/07/2006 while input is 31/12/2006
So, I think query works correctly
Rextester demo in more readable format with cte

Get the maximum values of column B per each distinct value of column A sql

I have this table:
I am trying to pull all records from this table for the max value in the DIST_NO column for every distinct ID in the left most column, but I still want to pull every record for each ID in which there are different Product_ID's as well.
I tried partitioning and using row_number, but I am having trouble at the moment.
Here are my desired results:
This is what my code looks like currently:
select *
from
(SELECT *,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DIST_NO DESC) RN
FROM Table) V
WHERE RN<=3
you want the max(DIST_NO) for each ID, product_ID?
If so, you can:
SELECT
ID, product_ID, max(DIST_NO)
from table
group by ID, product_ID
If you want the detail rows related to the max row, you just need to join it back to your table:
Select
t.ID, max_dist_no, TRANSaction_ID , LINE_NO , PRODUCT_ID
from
table t inner join
(SELECT
ID, max(DIST_NO) as max_dist_no
from table
group by ID) mx on
t.ID = mx.ID and
t.DIST_NO = max_DIST_NO
Try
SELECT MT.ID
, MT.DIST_NO
, MT.TRANS_ID
, MT.LINE_NO
, MT.PRODUCT_ID
FROM MYTABLE MT
INNER JOIN (
SELECT T.ID, MAX(T.DIST_NO) as DIST_NO FROM MYTABLE T
GROUP BY T.ID
) MAX_MT ON MT.Id = MAX_MT.ID AND MT.DIST_NO = MAX_MT.DIST_NO
The sub query returns each combination of ID and Max value of DIST_NO:
SELECT T.ID, MAX(T.DIST_NO) as DIST_NO FROM MYTABLE T
GROUP BY T.ID
Joining this back to your original table will basically filter your original data-set by only these combinations of values.
Tested on PostgreSQL:
WITH t1 AS (
SELECT id, product_id, MAX(dist_no) AS dist_no
FROM test
GROUP BY 1,2)
SELECT t1.id, t1.dist_no, t2.trans_id, t2.line_no, t1.product_id
FROM test t2, t1
WHERE t1.id=t2.id AND t1.product_id=t2.product_id AND t1.dist_no=t2.dist_no
Use rank() or dense_rank():
select t.*
from (SELECT t.*
RANK() OVER (PARTITION BY ID ORDER BY DIST_NO DESC) as seqnum
FROM Table t
) t
WHERE seqnum = 1;
This is almost a literal translation of your request:
I am trying to pull all records from this table for the max value in
the DIST_NO column for every distinct ID in the left most column.
you can try something like this one :). (But is your result correct? I think there is little mistake in TRANS_ID...)
DECLARE #ExampleTable TABLE
(ID INT,
DIST_NO INT,
TRANS_ID INT,
LINE_NO INT,
PRODUCT_ID INT)
INSERT INTO #ExampleTable
( ID, DIST_NO, TRANS_ID,LINE_NO, PRODUCT_ID )
VALUES ( 102657, 1, 1105365, 1, 109119 ),
( 102657, 1, 1105366, 2, 109114 ),
( 102657, 2, 1105365, 1, 109119 ),
( 102657, 2, 1105366, 2, 109114 ),
( 104371, 1, 1190538, 1, 110981 ),
( 104371, 2, 1190538, 1, 110981 )
;WITH CTE AS ( SELECT DISTINCT ID, LINE_NO
FROM #ExampleTable)
SELECT a.ID,
x.DIST_NO,
x.TRANS_ID,
x.LINE_NO,
x.PRODUCT_ID
FROM CTE a
CROSS APPLY (SELECT TOP 1 *
FROM #ExampleTable f
WHERE a.ID = f.ID AND
a.LINE_NO = f. LINE_NO
ORDER BY DIST_NO DESC) x

Find most recent record by date

This is my original data (anonymised):
id usage verified date
1 4000 Y 2015-03-20
2 5000 N 2015-06-20
3 6000 N 2015-07-20
4 7000 Y 2016-09-20
Original query:
SELECT
me.usage,
mes.verified,
mes.date
FROM
Table1 me,
Table2 mes,
Table3 m,
Table4 mp
WHERE
me.theFk=mes.id
AND mes.theFk=m.id
AND m.theFk=mp.id
How would I go about selecting the most recent verified and non-verified?
So I would be left with:
id usage verified date
1 6000 N 2015-07-20
2 7000 Y 2016-09-20
I am using Microsoft SQL Server 2012.
First, do not use implicit joins. This was discontinued more than 10 years ago.
Second, embrace the power of the CTE, the in clause and row_number:
with CTE as
(
select
me.usage,
mes.verified,
mes.date,
row_number() over (partition by Verified order by Date desc) as CTEOrd
from Table1 me
inner join Table2 mes
on me.theFK = mes.id
where mes.theFK in
(
select m.id
from Table3 m
inner join Table4 mp
on mp.id = m.theFK
)
)
select CTE.*
from CTE
where CTEOrd = 1
You can select the TOP 1 ordered by date for verified=N, union'd with the TOP 1 ordered by date for verified=Y.
Or in pseudo SQL:
SELECT TOP 1 ...fields ...
FROM ...tables/joins...
WHERE Verified = 'N'
ORDER BY Date DESC
UNION
SELECT TOP 1 ...fields ...
FROM ...tables/joins...
WHERE Verified = 'Y'
ORDER BY Date DESC
drop table #stack2
CREATE TABLE #stack2
([id] int, [usage] int, [verified] varchar(1), [date] datetime)
;
INSERT INTO #stack2
([id], [usage], [verified], [date])
VALUES
(1, 4000, 'Y', '2015-03-20 00:00:00'),
(2, 5000, 'N', '2015-06-20 00:00:00'),
(3, 6000, 'N', '2015-07-20 00:00:00'),
(4, 7000, 'Y', '2016-09-20 00:00:00')
;
;with cte as (select verified,max(date) d from #stack2 group by verified)
select row_number() over( order by s2.[verified]),s2.[usage], s2.[verified], s2.[date] from #stack2 s2 join cte c on c.verified=s2.verified and c.d=s2.date
As per the data shown i had written the query.
for your scenario this will be use full
WITH cte1
AS (SELECT me.usage,
mes.verified,
mes.date
FROM Table1 me,
Table2 mes,
Table3 m,
Table4 mp
WHERE me.theFk = mes.id
AND mes.theFk = m.id
AND m.theFk = mp.id),
cte
AS (SELECT verified,
Max(date) d
FROM cte1
GROUP BY verified)
SELECT Row_number()
OVER(
ORDER BY s2.[verified]),
s2.[usage],
s2.[verified],
s2.[date]
FROM cte1 s2
JOIN cte c
ON c.verified = s2.verified
AND c.d = s2.date
You can as the below Without join.
-- Mock data
DECLARE #Tbl TABLE (id INT, usage INT, verified CHAR(1), date DATETIME)
INSERT INTO #Tbl
VALUES
(1, 4000 ,'Y', '2015-03-20'),
(2, 5000 ,'N', '2015-06-20'),
(3, 6000 ,'N', '2015-07-20'),
(4, 7000 ,'Y', '2016-09-20')
SELECT
A.id ,
A.usage ,
A.verified ,
A.MaxDate
FROM
(
SELECT
id ,
usage ,
verified ,
date,
MAX(date) OVER (PARTITION BY verified) MaxDate
FROM
#Tbl
) A
WHERE
A.date = A.MaxDate
Result:
id usage verified MaxDate
----------- ----------- -------- ----------
3 6000 N 2015-07-20
4 7000 Y 2016-09-20
CREATE TABLE #Table ( ID INT ,usage INT, verified VARCHAR(10), _date DATE)
INSERT INTO #Table ( ID , usage , verified , _date)
SELECT 1,4000 , 'Y','2015-03-20' UNION ALL
SELECT 2, 5000 , 'N' ,'2015-06-20' UNION ALL
SELECT 3, 6000 , 'N' ,'2015-07-20' UNION ALL
SELECT 4, 7000 , 'Y' ,'2016-09-20'
SELECT ROW_NUMBER() OVER(ORDER BY usage) ID,usage , A.verified , A._date
FROM #Table
JOIN
(
SELECT verified , MAX(_date) _date
FROM #Table
GROUP BY verified
) A ON #Table._date = A._date