Help in re-write a query
-
Friday, February 01, 2013 9:05 AM
Hi All,
I need help in re-writing the below query using CTE or any other method which would help in better performance.
Here is sample test data and requirement.
create table Users
(
[user_id] int identity(1,1) primary key,
Email varchar(50),
Gender char(1),
Age int,
name varchar(100)
)
go
create table Subscriptions
(
subscription_id int identity(1,1) primary key,
[user_id] int,
subscription_type varchar(50),
active_indicator varchar(3)
)
ALTER TABLE Subscriptions ADD CONSTRAINT uc_user_id UNIQUE ([user_id],subscription_type)
ALTER TABLE Subscriptions ADD FOREIGN KEY ([user_id]) REFERENCES Users([user_id])
gocreate table Transactions
(
subscription_id int not null,
[action] varchar(50) not null,
[timestamp] datetime not null
)
ALTER TABLE Transactions ADD CONSTRAINT pk_Transactions PRIMARY KEY (subscription_id,[action],[timestamp])
ALTER TABLE Transactions ADD FOREIGN KEY (subscription_id) REFERENCES Subscriptions(subscription_id)
go
insert into Users(Email,Gender,Age,name)
select 'a@a.com','m',30,'rob'
union all
select 'a@a.com','m',31,'robert'
union all
select 'b@b.com','f',18,'lucie'
union all
select 'b@b.com','f',22,'lulu'
union all
select 'c@c.com','m',10,'kim'
union all
select 'c@c.com','f',18,'kim'
union all
select 'c@c.com','f',08,'kim'
union all
select 'd@d.com','f',18,'JJ'
union all
select 'd@d.com','m',22,'Jay'
union all
select 'e@e.com','f',88,'Bill'
union all
select 'e@e.com','f',88,'Will'
union all
select 'e@e.com','f',60,'Will'
union all
select 'f@f.com','m',70,'Geor'
insert into Subscriptions([user_id],subscription_type,active_indicator)
select 2,'Magazine','Yes'
union all
select 3,'Music CD','No'
union all
select 3,'Magazine','Yes'
union all
select 3,'Video','Yes'
union all
select 8,'Magazine','Yes'
union all
select 9,'Video','Yes'
union all
select 10,'Magazine','No'
union all
select 13,'Magazine','Yes'insert into Transactions
select 1,'Renewal','2002-sep-10'
union all
select 2,'Renewal','2002-Jan-01'
union all
select 2,'Cancellation','2002-Feb-01'
union all
select 3,'Renewal','2002-Aug-20'
union all
select 4,'Renewal','2002-Aug-01'
union all
select 4,'Renewal','2002-Sep-01'
union all
select 5,'Renewal','2002-Aug-01'
union all
select 6,'Renewal','2001-Sep-01'
union all
select 7,'Renewal','2002-Sep-01'
union all
select 7,'Cancellation','2002-Sep-10'Requirement
=========
Generate a list of unique email addresses with the latest name, gender and age for a user with that email
The selection criteria limits the list to users which never subscribed to anything; or; users with inactive subscriptions; or;
users with active subscriptions that renewed between Sep 1st and Sep 30th of any yearanswer should be:
a@a.com m 31 robert
b@b.com f 22 lulu
c@c.com f 08 kim
d@d.com m 22 Jay
e@e.com f 60 WillMy Solution
========
select Email, Gender,Age, name from Users a
where user_id in
(select MAX(user_id) from Users b
where user_id in
(-- users never subscribed for anything
select USER_ID from Users where user_id not in (select user_id from Subscriptions)
union all
-- users with inactive subscriptions;
select [user_id] from Subscriptions where active_indicator = 'No'
union all
--users with active subscriptions that renewed between Sep 1st and Sep 30th of any year
select [user_id] from Subscriptions where subscription_id in (
select subscription_id from Transactions where action = 'Renewal' and datepart(month,timestamp) = 9
and subscription_id in (select subscription_id from Subscriptions where active_indicator='yes') )
)
and b.email = a.email
)Thanks in advance.
All Replies
-
Friday, February 01, 2013 9:24 AMAnswererselect * from
(
select u.*,row_number() over (partition by email order by u.user_id desc) rn
from Users u left join
Subscriptions s on u.user_id=s.user_id
where s.user_id is null or active_indicator = 'No'
or
subscription_id in (
select subscription_id from Transactions where action = 'Renewal' and datepart(month,timestamp) = 9
and subscription_id in (select subscription_id from Subscriptions where active_indicator='yes') )
) as der where rn=1Best Regards,Uri Dimant SQL Server MVP, http://sqlblog.com/blogs/uri_dimant/
MS SQL optimization: MS SQL Development and Optimization
MS SQL Blog: Large scale of database and data cleansing
Remote DBA Services: Improves MS SQL Database Performance
-
Friday, February 01, 2013 12:18 PM
Chk
;With Cte As
(
Select T1.User_Id,Email,Gender,Age,Name,T3.TimeStamp,Max(T1.User_ID) Over (Partition By T1.Email) As ActUser
From Users T1
Left Join Subscriptions T2 On T1.user_id = T2.user_id
Left JOin Transactions T3 On T2.subscription_id = T3.subscription_id
Where T3.action = 'Renewal' Or T2.active_indicator = 'No' Or T2.User_Id Is Null
)
,Res As(
Select *,Max(TimeStamp) Over (Partition By ActUser) MaxDate From Cte where User_Id = ActUser
)
Select Email,Gender,Age,Name From Res
Where Coalesce(TimeStamp,'') = Coalesce(MaxDate,'')Please have look on the comment
- Proposed As Answer by Sapen2 Friday, February 01, 2013 7:21 PM
- Marked As Answer by Kalman TothMicrosoft Community Contributor, Moderator Sunday, February 10, 2013 10:11 AM
-
Friday, February 01, 2013 6:05 PMThanks you very much. :-)

