Here is a recursive CTE solution using a technique that Paul White blogged about in Performance Tuning the Whole Query Plan.
declare @T table
(
Eventdate date index IX_Eventdate clustered,
Val int
);
insert into @T(Eventdate, Val) values
('2012-03-23', 3965),
('2012-03-26', 3979),
('2012-03-27', 3974),
('2012-03-28', 3965),
('2012-03-29', 3967),
('2012-03-30', 3959),
('2012-04-02', 3951),
('2012-04-03', 3961),
('2012-04-04', 3944),
('2012-04-05', 3935),
('2012-04-09', 3901),
('2012-04-10', 3822);
with C as
(
select top(1)
T.Eventdate,
T.Val,
T.Val as PrevVal1,
T.Val as PrevVal2
from @T as T
order by T.eventdate
union all
select T.Eventdate,
T.Val,
T.PrevVal1,
T.PrevVal2
from (
select T.Eventdate,
T.Val,
iif(abs(T.Val - C.PrevVal1) <= 12, C.PrevVal1, T.Val) as PrevVal1,
iif(abs(T.Val - C.PrevVal1) <= 12, null, T.Val) as PrevVal2,
row_number() over(order by T.Eventdate) as rn
from @T as T
inner join C
on C.Eventdate < T.Eventdate
) as T
where T.rn = 1
)
select C.Eventdate,
C.PrevVal2 as Val
from C
order by C.Eventdate
option (maxrecursion 0);
Using standard SQL on most RDBMS, there are various ways.
Using a subquery:
SELECT d.dept, d.role1, d.role2, DEF
FROM data d
INNER JOIN (
SELECT dept, role1, role2
FROM data
GROUP BY dept, role1, role2
HAVING COUNT(distinct DEF) > 1
) dup
ON dup.dept = d.dept AND dup.role1 = d.role1 AND dup.role2 = d.role2
;
The subquery returns sets of dept/role1/role2
with more than 1 distinct DEF
.
Using a correlated subquery:
SELECT d.dept, d.role1, d.role2, DEF
FROM @data d
WHERE EXISTS (
SELECT 1
FROM @data
WHERE dept = d.dept AND role1 = d.role1 AND role2 = d.role2 AND DEF <> d.DEF
);
The subquery return 0 to n rows. If at least one row exists, the row from the main table is returned.
Using CROSS APPLY
:
SELECT d.dept, d.role1, d.role2, d.DEF
FROM @data d
CROSS APPLY (
SELECT n=1
FROM @data
WHERE dept = d.dept AND role1 = d.role1 AND role2 = d.role2 AND DEF <> d.DEF
) ca
;
CROSS APPLY works with Oracle or SQL Server.
Output:
dept role1 role2 DEF
a abc er 0
a abc er 1
Best Answer
You should be able to use conditional aggregation to get the username with both a value in
col2
as well asnull
.I'd suggest using a HAVING clause with the conditions. The query would be similar to:
See SQL Fiddle with Demo. This query groups your data by each username and then uses conditional logic to check if
col2
meets both conditions you want - wherecol2
is not null andcol2
is null.You can then use this in a subquery, etc to get the
username
andcol2
values:See SQL Fiddle with Demo.
If you have more than one
col2
row with bothnull
and another value, then you just need to alter theHAVING
clause slightly:See SQL Fiddle with Demo