How Result using cross apply, can achieve using any other joins like inner,left,right join in sql server





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







3















This is my SQL script with sample data



CREATE TABLE [dbo].[Employee]
(
[ID] [INT] IDENTITY(1,1) NOT NULL,
[Name] [VARCHAR](100) NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[LoginEntry]
(
[ID] [INT] IDENTITY(1,1) NOT NULL,
[LoginTime] [DATETIME] NULL,
[EmpID] [INT] NULL,
[GateNumber] [VARCHAR](50) NULL
) ON [PRIMARY]
GO

ALTER TABLE Employee
ADD CONSTRAINT Pk_Employee PRIMARY KEY (Id)
GO

ALTER TABLE LoginEntry
ADD CONSTRAINT Fk_LoginEntry_Employee
FOREIGN KEY (EmpId) REFERENCES Employee(Id)
GO

SET IDENTITY_INSERT [dbo].[Employee] ON
GO

INSERT [dbo].[Employee] ([ID], [Name])
VALUES (1, N'Employee 1'), (2, N'Employee 2'), (3, N'Employee 3'),
(4, N'Employee 4'), (5, N'Employee 5'), (6, N'Employee 6')
GO

SET IDENTITY_INSERT [dbo].[Employee] OFF
GO


SET IDENTITY_INSERT [dbo].[LoginEntry] ON
GO

INSERT [dbo].[LoginEntry] ([ID], [LoginTime], [EmpID], [GateNumber])
VALUES (1, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 1, N'Gate 1'),
(2, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 1, N'Gate 1'),
(3, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 1, N'Gate 2'),
(4, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 2, N'Gate 1'),
(5, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 2, N'Gate 1'),
(6, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 2, N'Gate 2'),
(7, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 3, N'Gate 1'),
(8, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 3, N'Gate 1'),
(9, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 3, N'Gate 2'),
(10, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 4, N'Gate 1'),
(11, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 4, N'Gate 1'),
(19, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 5, N'Gate 1'),
(20, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 5, N'Gate 1'),
(21, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 5, N'Gate 2'),
(22, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 6, N'Gate 1'),
(23, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 6, N'Gate 1'),
(24, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 6, N'Gate 2')

SET IDENTITY_INSERT [dbo].[LoginEntry] OFF
GO


SELECT
e.ID, dt.EmpId, Name, LoginTime
FROM
Employee e
CROSS APPLY
(SELECT TOP 1
l.ID, l.LoginTime, l.EmpId
FROM
LoginEntry l
WHERE
l.EmpId = e.id) dt
GO


The result I get:



ID  EmpId   Name            LoginTime
-----------------------------------------------
1 1 Employee 1 2014-10-24 08:00:00.000
2 2 Employee 2 2014-10-24 08:00:00.000
3 3 Employee 3 2014-10-24 08:00:00.000
4 4 Employee 4 2014-10-24 08:00:00.000
5 5 Employee 5 2014-10-24 08:00:00.000
6 6 Employee 6 2014-10-24 08:00:00.000


I am Expecting the same result using Joins(inner,right,left,full) in sql server i tried my luck but couldn't, pls can any one help me out thanks in advance










share|improve this question




















  • 2





    Seriously, this is a good way to ask question. you only missed the 'order by' in the cross join.

    – MEdwin
    Nov 22 '18 at 10:21


















3















This is my SQL script with sample data



CREATE TABLE [dbo].[Employee]
(
[ID] [INT] IDENTITY(1,1) NOT NULL,
[Name] [VARCHAR](100) NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[LoginEntry]
(
[ID] [INT] IDENTITY(1,1) NOT NULL,
[LoginTime] [DATETIME] NULL,
[EmpID] [INT] NULL,
[GateNumber] [VARCHAR](50) NULL
) ON [PRIMARY]
GO

ALTER TABLE Employee
ADD CONSTRAINT Pk_Employee PRIMARY KEY (Id)
GO

ALTER TABLE LoginEntry
ADD CONSTRAINT Fk_LoginEntry_Employee
FOREIGN KEY (EmpId) REFERENCES Employee(Id)
GO

SET IDENTITY_INSERT [dbo].[Employee] ON
GO

INSERT [dbo].[Employee] ([ID], [Name])
VALUES (1, N'Employee 1'), (2, N'Employee 2'), (3, N'Employee 3'),
(4, N'Employee 4'), (5, N'Employee 5'), (6, N'Employee 6')
GO

SET IDENTITY_INSERT [dbo].[Employee] OFF
GO


SET IDENTITY_INSERT [dbo].[LoginEntry] ON
GO

INSERT [dbo].[LoginEntry] ([ID], [LoginTime], [EmpID], [GateNumber])
VALUES (1, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 1, N'Gate 1'),
(2, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 1, N'Gate 1'),
(3, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 1, N'Gate 2'),
(4, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 2, N'Gate 1'),
(5, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 2, N'Gate 1'),
(6, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 2, N'Gate 2'),
(7, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 3, N'Gate 1'),
(8, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 3, N'Gate 1'),
(9, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 3, N'Gate 2'),
(10, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 4, N'Gate 1'),
(11, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 4, N'Gate 1'),
(19, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 5, N'Gate 1'),
(20, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 5, N'Gate 1'),
(21, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 5, N'Gate 2'),
(22, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 6, N'Gate 1'),
(23, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 6, N'Gate 1'),
(24, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 6, N'Gate 2')

SET IDENTITY_INSERT [dbo].[LoginEntry] OFF
GO


SELECT
e.ID, dt.EmpId, Name, LoginTime
FROM
Employee e
CROSS APPLY
(SELECT TOP 1
l.ID, l.LoginTime, l.EmpId
FROM
LoginEntry l
WHERE
l.EmpId = e.id) dt
GO


The result I get:



ID  EmpId   Name            LoginTime
-----------------------------------------------
1 1 Employee 1 2014-10-24 08:00:00.000
2 2 Employee 2 2014-10-24 08:00:00.000
3 3 Employee 3 2014-10-24 08:00:00.000
4 4 Employee 4 2014-10-24 08:00:00.000
5 5 Employee 5 2014-10-24 08:00:00.000
6 6 Employee 6 2014-10-24 08:00:00.000


I am Expecting the same result using Joins(inner,right,left,full) in sql server i tried my luck but couldn't, pls can any one help me out thanks in advance










share|improve this question




















  • 2





    Seriously, this is a good way to ask question. you only missed the 'order by' in the cross join.

    – MEdwin
    Nov 22 '18 at 10:21














3












3








3


2






This is my SQL script with sample data



CREATE TABLE [dbo].[Employee]
(
[ID] [INT] IDENTITY(1,1) NOT NULL,
[Name] [VARCHAR](100) NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[LoginEntry]
(
[ID] [INT] IDENTITY(1,1) NOT NULL,
[LoginTime] [DATETIME] NULL,
[EmpID] [INT] NULL,
[GateNumber] [VARCHAR](50) NULL
) ON [PRIMARY]
GO

ALTER TABLE Employee
ADD CONSTRAINT Pk_Employee PRIMARY KEY (Id)
GO

ALTER TABLE LoginEntry
ADD CONSTRAINT Fk_LoginEntry_Employee
FOREIGN KEY (EmpId) REFERENCES Employee(Id)
GO

SET IDENTITY_INSERT [dbo].[Employee] ON
GO

INSERT [dbo].[Employee] ([ID], [Name])
VALUES (1, N'Employee 1'), (2, N'Employee 2'), (3, N'Employee 3'),
(4, N'Employee 4'), (5, N'Employee 5'), (6, N'Employee 6')
GO

SET IDENTITY_INSERT [dbo].[Employee] OFF
GO


SET IDENTITY_INSERT [dbo].[LoginEntry] ON
GO

INSERT [dbo].[LoginEntry] ([ID], [LoginTime], [EmpID], [GateNumber])
VALUES (1, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 1, N'Gate 1'),
(2, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 1, N'Gate 1'),
(3, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 1, N'Gate 2'),
(4, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 2, N'Gate 1'),
(5, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 2, N'Gate 1'),
(6, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 2, N'Gate 2'),
(7, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 3, N'Gate 1'),
(8, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 3, N'Gate 1'),
(9, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 3, N'Gate 2'),
(10, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 4, N'Gate 1'),
(11, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 4, N'Gate 1'),
(19, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 5, N'Gate 1'),
(20, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 5, N'Gate 1'),
(21, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 5, N'Gate 2'),
(22, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 6, N'Gate 1'),
(23, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 6, N'Gate 1'),
(24, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 6, N'Gate 2')

SET IDENTITY_INSERT [dbo].[LoginEntry] OFF
GO


SELECT
e.ID, dt.EmpId, Name, LoginTime
FROM
Employee e
CROSS APPLY
(SELECT TOP 1
l.ID, l.LoginTime, l.EmpId
FROM
LoginEntry l
WHERE
l.EmpId = e.id) dt
GO


The result I get:



ID  EmpId   Name            LoginTime
-----------------------------------------------
1 1 Employee 1 2014-10-24 08:00:00.000
2 2 Employee 2 2014-10-24 08:00:00.000
3 3 Employee 3 2014-10-24 08:00:00.000
4 4 Employee 4 2014-10-24 08:00:00.000
5 5 Employee 5 2014-10-24 08:00:00.000
6 6 Employee 6 2014-10-24 08:00:00.000


I am Expecting the same result using Joins(inner,right,left,full) in sql server i tried my luck but couldn't, pls can any one help me out thanks in advance










share|improve this question
















This is my SQL script with sample data



CREATE TABLE [dbo].[Employee]
(
[ID] [INT] IDENTITY(1,1) NOT NULL,
[Name] [VARCHAR](100) NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[LoginEntry]
(
[ID] [INT] IDENTITY(1,1) NOT NULL,
[LoginTime] [DATETIME] NULL,
[EmpID] [INT] NULL,
[GateNumber] [VARCHAR](50) NULL
) ON [PRIMARY]
GO

ALTER TABLE Employee
ADD CONSTRAINT Pk_Employee PRIMARY KEY (Id)
GO

ALTER TABLE LoginEntry
ADD CONSTRAINT Fk_LoginEntry_Employee
FOREIGN KEY (EmpId) REFERENCES Employee(Id)
GO

SET IDENTITY_INSERT [dbo].[Employee] ON
GO

INSERT [dbo].[Employee] ([ID], [Name])
VALUES (1, N'Employee 1'), (2, N'Employee 2'), (3, N'Employee 3'),
(4, N'Employee 4'), (5, N'Employee 5'), (6, N'Employee 6')
GO

SET IDENTITY_INSERT [dbo].[Employee] OFF
GO


SET IDENTITY_INSERT [dbo].[LoginEntry] ON
GO

INSERT [dbo].[LoginEntry] ([ID], [LoginTime], [EmpID], [GateNumber])
VALUES (1, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 1, N'Gate 1'),
(2, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 1, N'Gate 1'),
(3, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 1, N'Gate 2'),
(4, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 2, N'Gate 1'),
(5, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 2, N'Gate 1'),
(6, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 2, N'Gate 2'),
(7, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 3, N'Gate 1'),
(8, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 3, N'Gate 1'),
(9, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 3, N'Gate 2'),
(10, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 4, N'Gate 1'),
(11, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 4, N'Gate 1'),
(19, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 5, N'Gate 1'),
(20, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 5, N'Gate 1'),
(21, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 5, N'Gate 2'),
(22, CAST(N'2014-10-24 08:00:00.000' AS DateTime), 6, N'Gate 1'),
(23, CAST(N'2014-10-24 09:00:00.000' AS DateTime), 6, N'Gate 1'),
(24, CAST(N'2014-10-24 10:00:00.000' AS DateTime), 6, N'Gate 2')

SET IDENTITY_INSERT [dbo].[LoginEntry] OFF
GO


SELECT
e.ID, dt.EmpId, Name, LoginTime
FROM
Employee e
CROSS APPLY
(SELECT TOP 1
l.ID, l.LoginTime, l.EmpId
FROM
LoginEntry l
WHERE
l.EmpId = e.id) dt
GO


The result I get:



ID  EmpId   Name            LoginTime
-----------------------------------------------
1 1 Employee 1 2014-10-24 08:00:00.000
2 2 Employee 2 2014-10-24 08:00:00.000
3 3 Employee 3 2014-10-24 08:00:00.000
4 4 Employee 4 2014-10-24 08:00:00.000
5 5 Employee 5 2014-10-24 08:00:00.000
6 6 Employee 6 2014-10-24 08:00:00.000


I am Expecting the same result using Joins(inner,right,left,full) in sql server i tried my luck but couldn't, pls can any one help me out thanks in advance







sql sql-server tsql






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 10:57









marc_s

585k13011261272




585k13011261272










asked Nov 22 '18 at 9:39









Sreenu131Sreenu131

1,601139




1,601139








  • 2





    Seriously, this is a good way to ask question. you only missed the 'order by' in the cross join.

    – MEdwin
    Nov 22 '18 at 10:21














  • 2





    Seriously, this is a good way to ask question. you only missed the 'order by' in the cross join.

    – MEdwin
    Nov 22 '18 at 10:21








2




2





Seriously, this is a good way to ask question. you only missed the 'order by' in the cross join.

– MEdwin
Nov 22 '18 at 10:21





Seriously, this is a good way to ask question. you only missed the 'order by' in the cross join.

– MEdwin
Nov 22 '18 at 10:21












3 Answers
3






active

oldest

votes


















5














First, your query is incomplete. When you use TOP 1 without an ORDER BY you never have a guarantee which one it will pick. New data, concurrent processes, re-indexing, software patches, the time of day, they all can cause the result to change.



So, it should be something like...



SELECT
e.ID,dt.EmpId,Name,LoginTime
FROM
Employee e
CROSS APPLY
(
SELECT TOP 1
l.ID
,l.LoginTime
,l.EmpId
FROM
LoginEntry l
WHERE
l.EmpId=e.id
ORDER BY
l.LoginTime DESC -- Will cause TOP 1 to pick the most recent value (per employee)
)
dt


As for doing it with joins, doing the TOP 1 (or greatest-n-per-group, for which your n is 1), is longer, messier, and slower. So I won't go in to that.



But you can use ROW_NUMBER() to do the TOP 1 part, and then use a JOIN to associate that result with your main table...



WITH
ordered_logins AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY EmpID ORDER BY LoginTime DESC, ID DESC) AS row_ordinal
FROM
LoginEntry
)
SELECT
e.ID, l.EmpId, e.Name, l.LoginTime
FROM
Employee e
LEFT JOIN
ordered_logins l
ON l.EmpID = e.ID
AND l.row_oridnal = 1


The ROW_NUMBER() assigns every row a value from 1 upwards (per EmpID - the partition clause). It's order by loginTime descending, so the latest logins are first, and just in case two logins have the exact same time, it's secondarily ordered by ID desc.



Then the LEFT JOIN only picks the rows numbered 1 (the latest logins) and if there are no logins gives NULLs instead (so that the employee record is Not discarded due to a lack of join).



Note: the LEFT JOIN equivalent for APPLY is to use OUTER APPLY instead of CROSS APPLY.






share|improve this answer


























  • Many thanks for the response with explanation

    – Sreenu131
    Nov 22 '18 at 9:58











  • not sure on efficiency, a quick test revealed that the row_number approach yielded the best performance, however an index on {employeeid, LoginTime} made the original query (plus the order by addition) faster.

    – Cato
    Nov 22 '18 at 10:06











  • @cato It really depends on the size of the table, the fragmentation of the indexes, etc. Also, making the index EmpID, LoginTime, ID would help the second query, so that there would be no need to join back to the underlying table to get the ID value for the ORDER BY. Really, I should have added ID to the ORDER BY in the first query too, but it didn't occur to me until I started on the second query. (Out of interest, how large and randomise was your test?)

    – MatBailie
    Nov 22 '18 at 10:11













  • I had very little data, just the data provided - doesn't row_number risk calculating a huge number of orderings that are not needed? We only need row_number 1, which is TOP 1, but we might be telling the query to sort 1000 records into order, then hand us #1. Or on the otherhand query optimisation might be really clever and be able to spot not doing that.

    – Cato
    Nov 22 '18 at 12:11











  • @cato - The same concern applies to using TOP and ORDER BY. How does it know which item is first if it's only ordered half of them, surely it needs to see all of them to know which is top? The answer is that the optimiser uses indexes, and predicate-push-down to know when it can stop bothering anymore. The concerns, consequences and internal optimisations are the same in both cases.

    – MatBailie
    Nov 22 '18 at 12:18





















3














Just for the sake of showing one more way to solve the problem, the "longer, messier, and slower" JOIN method that (I thought) MatBailie didn't show would look like this:



SELECT TOP (1) WITH TIES
e.ID
,l.EmpID
,e.Name
,l.LoginTime
FROM
dbo.Employee AS e
JOIN
dbo.LoginEntry AS l
ON
l.EmpID = e.ID
ORDER BY
ROW_NUMBER() OVER (PARTITION BY e.ID ORDER BY l.LoginTime DESC, ID DESC)


The ROW_NUMBER in the ORDER BY clause takes all of the logins for each Employee ID and numbers them by LoginTime with the most recent first (and using the LoginEntry ID as tie breaker, and thanks for that touch, Mat).



Then, the SELECT TOP (1) WITH TIES does its thing. The WITH TIES bit means that it selects the number one result from each PARTITION BY group in the ORDER BY clause.






share|improve this answer


























  • The longer and messier one that I didn't show is e JOIN l JOIN (SELECT emp, MAX(time) FROM l). But, I didn't realise SQL Server supported ROW_NUMBER() in the ORDER BY, I'll have to try to remember that. Much tidier :)

    – MatBailie
    Nov 22 '18 at 11:15













  • Oh, eww. But right. I've certainly seen that. I hope I've never written it...

    – Eric Brandt
    Nov 22 '18 at 11:19











  • I started before analytic functions were commonly supported, and have had to use MySQL.

    – MatBailie
    Nov 22 '18 at 11:21











  • I started out using Access97, so there's some (I know now) kludgy code in my past, too. But we work with the tools we have, right?

    – Eric Brandt
    Nov 22 '18 at 11:25



















2














you can use window function row_number()



    with cte as(    
SELECT e.ID,l.EmpId,Name,l.LoginTime, row_number() over(partition by e.ID order by l.LoginTime) as rn
FROM Employee e join LoginEntry l on l.EmpId=e.id
) select ID,EmpId,Name,LoginTime from cte where rn=1


demo link






share|improve this answer


























  • Thank You Very much

    – Sreenu131
    Nov 22 '18 at 9:52












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53427881%2fhow-result-using-cross-apply-can-achieve-using-any-other-joins-like-inner-left%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









5














First, your query is incomplete. When you use TOP 1 without an ORDER BY you never have a guarantee which one it will pick. New data, concurrent processes, re-indexing, software patches, the time of day, they all can cause the result to change.



So, it should be something like...



SELECT
e.ID,dt.EmpId,Name,LoginTime
FROM
Employee e
CROSS APPLY
(
SELECT TOP 1
l.ID
,l.LoginTime
,l.EmpId
FROM
LoginEntry l
WHERE
l.EmpId=e.id
ORDER BY
l.LoginTime DESC -- Will cause TOP 1 to pick the most recent value (per employee)
)
dt


As for doing it with joins, doing the TOP 1 (or greatest-n-per-group, for which your n is 1), is longer, messier, and slower. So I won't go in to that.



But you can use ROW_NUMBER() to do the TOP 1 part, and then use a JOIN to associate that result with your main table...



WITH
ordered_logins AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY EmpID ORDER BY LoginTime DESC, ID DESC) AS row_ordinal
FROM
LoginEntry
)
SELECT
e.ID, l.EmpId, e.Name, l.LoginTime
FROM
Employee e
LEFT JOIN
ordered_logins l
ON l.EmpID = e.ID
AND l.row_oridnal = 1


The ROW_NUMBER() assigns every row a value from 1 upwards (per EmpID - the partition clause). It's order by loginTime descending, so the latest logins are first, and just in case two logins have the exact same time, it's secondarily ordered by ID desc.



Then the LEFT JOIN only picks the rows numbered 1 (the latest logins) and if there are no logins gives NULLs instead (so that the employee record is Not discarded due to a lack of join).



Note: the LEFT JOIN equivalent for APPLY is to use OUTER APPLY instead of CROSS APPLY.






share|improve this answer


























  • Many thanks for the response with explanation

    – Sreenu131
    Nov 22 '18 at 9:58











  • not sure on efficiency, a quick test revealed that the row_number approach yielded the best performance, however an index on {employeeid, LoginTime} made the original query (plus the order by addition) faster.

    – Cato
    Nov 22 '18 at 10:06











  • @cato It really depends on the size of the table, the fragmentation of the indexes, etc. Also, making the index EmpID, LoginTime, ID would help the second query, so that there would be no need to join back to the underlying table to get the ID value for the ORDER BY. Really, I should have added ID to the ORDER BY in the first query too, but it didn't occur to me until I started on the second query. (Out of interest, how large and randomise was your test?)

    – MatBailie
    Nov 22 '18 at 10:11













  • I had very little data, just the data provided - doesn't row_number risk calculating a huge number of orderings that are not needed? We only need row_number 1, which is TOP 1, but we might be telling the query to sort 1000 records into order, then hand us #1. Or on the otherhand query optimisation might be really clever and be able to spot not doing that.

    – Cato
    Nov 22 '18 at 12:11











  • @cato - The same concern applies to using TOP and ORDER BY. How does it know which item is first if it's only ordered half of them, surely it needs to see all of them to know which is top? The answer is that the optimiser uses indexes, and predicate-push-down to know when it can stop bothering anymore. The concerns, consequences and internal optimisations are the same in both cases.

    – MatBailie
    Nov 22 '18 at 12:18


















5














First, your query is incomplete. When you use TOP 1 without an ORDER BY you never have a guarantee which one it will pick. New data, concurrent processes, re-indexing, software patches, the time of day, they all can cause the result to change.



So, it should be something like...



SELECT
e.ID,dt.EmpId,Name,LoginTime
FROM
Employee e
CROSS APPLY
(
SELECT TOP 1
l.ID
,l.LoginTime
,l.EmpId
FROM
LoginEntry l
WHERE
l.EmpId=e.id
ORDER BY
l.LoginTime DESC -- Will cause TOP 1 to pick the most recent value (per employee)
)
dt


As for doing it with joins, doing the TOP 1 (or greatest-n-per-group, for which your n is 1), is longer, messier, and slower. So I won't go in to that.



But you can use ROW_NUMBER() to do the TOP 1 part, and then use a JOIN to associate that result with your main table...



WITH
ordered_logins AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY EmpID ORDER BY LoginTime DESC, ID DESC) AS row_ordinal
FROM
LoginEntry
)
SELECT
e.ID, l.EmpId, e.Name, l.LoginTime
FROM
Employee e
LEFT JOIN
ordered_logins l
ON l.EmpID = e.ID
AND l.row_oridnal = 1


The ROW_NUMBER() assigns every row a value from 1 upwards (per EmpID - the partition clause). It's order by loginTime descending, so the latest logins are first, and just in case two logins have the exact same time, it's secondarily ordered by ID desc.



Then the LEFT JOIN only picks the rows numbered 1 (the latest logins) and if there are no logins gives NULLs instead (so that the employee record is Not discarded due to a lack of join).



Note: the LEFT JOIN equivalent for APPLY is to use OUTER APPLY instead of CROSS APPLY.






share|improve this answer


























  • Many thanks for the response with explanation

    – Sreenu131
    Nov 22 '18 at 9:58











  • not sure on efficiency, a quick test revealed that the row_number approach yielded the best performance, however an index on {employeeid, LoginTime} made the original query (plus the order by addition) faster.

    – Cato
    Nov 22 '18 at 10:06











  • @cato It really depends on the size of the table, the fragmentation of the indexes, etc. Also, making the index EmpID, LoginTime, ID would help the second query, so that there would be no need to join back to the underlying table to get the ID value for the ORDER BY. Really, I should have added ID to the ORDER BY in the first query too, but it didn't occur to me until I started on the second query. (Out of interest, how large and randomise was your test?)

    – MatBailie
    Nov 22 '18 at 10:11













  • I had very little data, just the data provided - doesn't row_number risk calculating a huge number of orderings that are not needed? We only need row_number 1, which is TOP 1, but we might be telling the query to sort 1000 records into order, then hand us #1. Or on the otherhand query optimisation might be really clever and be able to spot not doing that.

    – Cato
    Nov 22 '18 at 12:11











  • @cato - The same concern applies to using TOP and ORDER BY. How does it know which item is first if it's only ordered half of them, surely it needs to see all of them to know which is top? The answer is that the optimiser uses indexes, and predicate-push-down to know when it can stop bothering anymore. The concerns, consequences and internal optimisations are the same in both cases.

    – MatBailie
    Nov 22 '18 at 12:18
















5












5








5







First, your query is incomplete. When you use TOP 1 without an ORDER BY you never have a guarantee which one it will pick. New data, concurrent processes, re-indexing, software patches, the time of day, they all can cause the result to change.



So, it should be something like...



SELECT
e.ID,dt.EmpId,Name,LoginTime
FROM
Employee e
CROSS APPLY
(
SELECT TOP 1
l.ID
,l.LoginTime
,l.EmpId
FROM
LoginEntry l
WHERE
l.EmpId=e.id
ORDER BY
l.LoginTime DESC -- Will cause TOP 1 to pick the most recent value (per employee)
)
dt


As for doing it with joins, doing the TOP 1 (or greatest-n-per-group, for which your n is 1), is longer, messier, and slower. So I won't go in to that.



But you can use ROW_NUMBER() to do the TOP 1 part, and then use a JOIN to associate that result with your main table...



WITH
ordered_logins AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY EmpID ORDER BY LoginTime DESC, ID DESC) AS row_ordinal
FROM
LoginEntry
)
SELECT
e.ID, l.EmpId, e.Name, l.LoginTime
FROM
Employee e
LEFT JOIN
ordered_logins l
ON l.EmpID = e.ID
AND l.row_oridnal = 1


The ROW_NUMBER() assigns every row a value from 1 upwards (per EmpID - the partition clause). It's order by loginTime descending, so the latest logins are first, and just in case two logins have the exact same time, it's secondarily ordered by ID desc.



Then the LEFT JOIN only picks the rows numbered 1 (the latest logins) and if there are no logins gives NULLs instead (so that the employee record is Not discarded due to a lack of join).



Note: the LEFT JOIN equivalent for APPLY is to use OUTER APPLY instead of CROSS APPLY.






share|improve this answer















First, your query is incomplete. When you use TOP 1 without an ORDER BY you never have a guarantee which one it will pick. New data, concurrent processes, re-indexing, software patches, the time of day, they all can cause the result to change.



So, it should be something like...



SELECT
e.ID,dt.EmpId,Name,LoginTime
FROM
Employee e
CROSS APPLY
(
SELECT TOP 1
l.ID
,l.LoginTime
,l.EmpId
FROM
LoginEntry l
WHERE
l.EmpId=e.id
ORDER BY
l.LoginTime DESC -- Will cause TOP 1 to pick the most recent value (per employee)
)
dt


As for doing it with joins, doing the TOP 1 (or greatest-n-per-group, for which your n is 1), is longer, messier, and slower. So I won't go in to that.



But you can use ROW_NUMBER() to do the TOP 1 part, and then use a JOIN to associate that result with your main table...



WITH
ordered_logins AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY EmpID ORDER BY LoginTime DESC, ID DESC) AS row_ordinal
FROM
LoginEntry
)
SELECT
e.ID, l.EmpId, e.Name, l.LoginTime
FROM
Employee e
LEFT JOIN
ordered_logins l
ON l.EmpID = e.ID
AND l.row_oridnal = 1


The ROW_NUMBER() assigns every row a value from 1 upwards (per EmpID - the partition clause). It's order by loginTime descending, so the latest logins are first, and just in case two logins have the exact same time, it's secondarily ordered by ID desc.



Then the LEFT JOIN only picks the rows numbered 1 (the latest logins) and if there are no logins gives NULLs instead (so that the employee record is Not discarded due to a lack of join).



Note: the LEFT JOIN equivalent for APPLY is to use OUTER APPLY instead of CROSS APPLY.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 22 '18 at 9:58

























answered Nov 22 '18 at 9:52









MatBailieMatBailie

60.8k1477112




60.8k1477112













  • Many thanks for the response with explanation

    – Sreenu131
    Nov 22 '18 at 9:58











  • not sure on efficiency, a quick test revealed that the row_number approach yielded the best performance, however an index on {employeeid, LoginTime} made the original query (plus the order by addition) faster.

    – Cato
    Nov 22 '18 at 10:06











  • @cato It really depends on the size of the table, the fragmentation of the indexes, etc. Also, making the index EmpID, LoginTime, ID would help the second query, so that there would be no need to join back to the underlying table to get the ID value for the ORDER BY. Really, I should have added ID to the ORDER BY in the first query too, but it didn't occur to me until I started on the second query. (Out of interest, how large and randomise was your test?)

    – MatBailie
    Nov 22 '18 at 10:11













  • I had very little data, just the data provided - doesn't row_number risk calculating a huge number of orderings that are not needed? We only need row_number 1, which is TOP 1, but we might be telling the query to sort 1000 records into order, then hand us #1. Or on the otherhand query optimisation might be really clever and be able to spot not doing that.

    – Cato
    Nov 22 '18 at 12:11











  • @cato - The same concern applies to using TOP and ORDER BY. How does it know which item is first if it's only ordered half of them, surely it needs to see all of them to know which is top? The answer is that the optimiser uses indexes, and predicate-push-down to know when it can stop bothering anymore. The concerns, consequences and internal optimisations are the same in both cases.

    – MatBailie
    Nov 22 '18 at 12:18





















  • Many thanks for the response with explanation

    – Sreenu131
    Nov 22 '18 at 9:58











  • not sure on efficiency, a quick test revealed that the row_number approach yielded the best performance, however an index on {employeeid, LoginTime} made the original query (plus the order by addition) faster.

    – Cato
    Nov 22 '18 at 10:06











  • @cato It really depends on the size of the table, the fragmentation of the indexes, etc. Also, making the index EmpID, LoginTime, ID would help the second query, so that there would be no need to join back to the underlying table to get the ID value for the ORDER BY. Really, I should have added ID to the ORDER BY in the first query too, but it didn't occur to me until I started on the second query. (Out of interest, how large and randomise was your test?)

    – MatBailie
    Nov 22 '18 at 10:11













  • I had very little data, just the data provided - doesn't row_number risk calculating a huge number of orderings that are not needed? We only need row_number 1, which is TOP 1, but we might be telling the query to sort 1000 records into order, then hand us #1. Or on the otherhand query optimisation might be really clever and be able to spot not doing that.

    – Cato
    Nov 22 '18 at 12:11











  • @cato - The same concern applies to using TOP and ORDER BY. How does it know which item is first if it's only ordered half of them, surely it needs to see all of them to know which is top? The answer is that the optimiser uses indexes, and predicate-push-down to know when it can stop bothering anymore. The concerns, consequences and internal optimisations are the same in both cases.

    – MatBailie
    Nov 22 '18 at 12:18



















Many thanks for the response with explanation

– Sreenu131
Nov 22 '18 at 9:58





Many thanks for the response with explanation

– Sreenu131
Nov 22 '18 at 9:58













not sure on efficiency, a quick test revealed that the row_number approach yielded the best performance, however an index on {employeeid, LoginTime} made the original query (plus the order by addition) faster.

– Cato
Nov 22 '18 at 10:06





not sure on efficiency, a quick test revealed that the row_number approach yielded the best performance, however an index on {employeeid, LoginTime} made the original query (plus the order by addition) faster.

– Cato
Nov 22 '18 at 10:06













@cato It really depends on the size of the table, the fragmentation of the indexes, etc. Also, making the index EmpID, LoginTime, ID would help the second query, so that there would be no need to join back to the underlying table to get the ID value for the ORDER BY. Really, I should have added ID to the ORDER BY in the first query too, but it didn't occur to me until I started on the second query. (Out of interest, how large and randomise was your test?)

– MatBailie
Nov 22 '18 at 10:11







@cato It really depends on the size of the table, the fragmentation of the indexes, etc. Also, making the index EmpID, LoginTime, ID would help the second query, so that there would be no need to join back to the underlying table to get the ID value for the ORDER BY. Really, I should have added ID to the ORDER BY in the first query too, but it didn't occur to me until I started on the second query. (Out of interest, how large and randomise was your test?)

– MatBailie
Nov 22 '18 at 10:11















I had very little data, just the data provided - doesn't row_number risk calculating a huge number of orderings that are not needed? We only need row_number 1, which is TOP 1, but we might be telling the query to sort 1000 records into order, then hand us #1. Or on the otherhand query optimisation might be really clever and be able to spot not doing that.

– Cato
Nov 22 '18 at 12:11





I had very little data, just the data provided - doesn't row_number risk calculating a huge number of orderings that are not needed? We only need row_number 1, which is TOP 1, but we might be telling the query to sort 1000 records into order, then hand us #1. Or on the otherhand query optimisation might be really clever and be able to spot not doing that.

– Cato
Nov 22 '18 at 12:11













@cato - The same concern applies to using TOP and ORDER BY. How does it know which item is first if it's only ordered half of them, surely it needs to see all of them to know which is top? The answer is that the optimiser uses indexes, and predicate-push-down to know when it can stop bothering anymore. The concerns, consequences and internal optimisations are the same in both cases.

– MatBailie
Nov 22 '18 at 12:18







@cato - The same concern applies to using TOP and ORDER BY. How does it know which item is first if it's only ordered half of them, surely it needs to see all of them to know which is top? The answer is that the optimiser uses indexes, and predicate-push-down to know when it can stop bothering anymore. The concerns, consequences and internal optimisations are the same in both cases.

– MatBailie
Nov 22 '18 at 12:18















3














Just for the sake of showing one more way to solve the problem, the "longer, messier, and slower" JOIN method that (I thought) MatBailie didn't show would look like this:



SELECT TOP (1) WITH TIES
e.ID
,l.EmpID
,e.Name
,l.LoginTime
FROM
dbo.Employee AS e
JOIN
dbo.LoginEntry AS l
ON
l.EmpID = e.ID
ORDER BY
ROW_NUMBER() OVER (PARTITION BY e.ID ORDER BY l.LoginTime DESC, ID DESC)


The ROW_NUMBER in the ORDER BY clause takes all of the logins for each Employee ID and numbers them by LoginTime with the most recent first (and using the LoginEntry ID as tie breaker, and thanks for that touch, Mat).



Then, the SELECT TOP (1) WITH TIES does its thing. The WITH TIES bit means that it selects the number one result from each PARTITION BY group in the ORDER BY clause.






share|improve this answer


























  • The longer and messier one that I didn't show is e JOIN l JOIN (SELECT emp, MAX(time) FROM l). But, I didn't realise SQL Server supported ROW_NUMBER() in the ORDER BY, I'll have to try to remember that. Much tidier :)

    – MatBailie
    Nov 22 '18 at 11:15













  • Oh, eww. But right. I've certainly seen that. I hope I've never written it...

    – Eric Brandt
    Nov 22 '18 at 11:19











  • I started before analytic functions were commonly supported, and have had to use MySQL.

    – MatBailie
    Nov 22 '18 at 11:21











  • I started out using Access97, so there's some (I know now) kludgy code in my past, too. But we work with the tools we have, right?

    – Eric Brandt
    Nov 22 '18 at 11:25
















3














Just for the sake of showing one more way to solve the problem, the "longer, messier, and slower" JOIN method that (I thought) MatBailie didn't show would look like this:



SELECT TOP (1) WITH TIES
e.ID
,l.EmpID
,e.Name
,l.LoginTime
FROM
dbo.Employee AS e
JOIN
dbo.LoginEntry AS l
ON
l.EmpID = e.ID
ORDER BY
ROW_NUMBER() OVER (PARTITION BY e.ID ORDER BY l.LoginTime DESC, ID DESC)


The ROW_NUMBER in the ORDER BY clause takes all of the logins for each Employee ID and numbers them by LoginTime with the most recent first (and using the LoginEntry ID as tie breaker, and thanks for that touch, Mat).



Then, the SELECT TOP (1) WITH TIES does its thing. The WITH TIES bit means that it selects the number one result from each PARTITION BY group in the ORDER BY clause.






share|improve this answer


























  • The longer and messier one that I didn't show is e JOIN l JOIN (SELECT emp, MAX(time) FROM l). But, I didn't realise SQL Server supported ROW_NUMBER() in the ORDER BY, I'll have to try to remember that. Much tidier :)

    – MatBailie
    Nov 22 '18 at 11:15













  • Oh, eww. But right. I've certainly seen that. I hope I've never written it...

    – Eric Brandt
    Nov 22 '18 at 11:19











  • I started before analytic functions were commonly supported, and have had to use MySQL.

    – MatBailie
    Nov 22 '18 at 11:21











  • I started out using Access97, so there's some (I know now) kludgy code in my past, too. But we work with the tools we have, right?

    – Eric Brandt
    Nov 22 '18 at 11:25














3












3








3







Just for the sake of showing one more way to solve the problem, the "longer, messier, and slower" JOIN method that (I thought) MatBailie didn't show would look like this:



SELECT TOP (1) WITH TIES
e.ID
,l.EmpID
,e.Name
,l.LoginTime
FROM
dbo.Employee AS e
JOIN
dbo.LoginEntry AS l
ON
l.EmpID = e.ID
ORDER BY
ROW_NUMBER() OVER (PARTITION BY e.ID ORDER BY l.LoginTime DESC, ID DESC)


The ROW_NUMBER in the ORDER BY clause takes all of the logins for each Employee ID and numbers them by LoginTime with the most recent first (and using the LoginEntry ID as tie breaker, and thanks for that touch, Mat).



Then, the SELECT TOP (1) WITH TIES does its thing. The WITH TIES bit means that it selects the number one result from each PARTITION BY group in the ORDER BY clause.






share|improve this answer















Just for the sake of showing one more way to solve the problem, the "longer, messier, and slower" JOIN method that (I thought) MatBailie didn't show would look like this:



SELECT TOP (1) WITH TIES
e.ID
,l.EmpID
,e.Name
,l.LoginTime
FROM
dbo.Employee AS e
JOIN
dbo.LoginEntry AS l
ON
l.EmpID = e.ID
ORDER BY
ROW_NUMBER() OVER (PARTITION BY e.ID ORDER BY l.LoginTime DESC, ID DESC)


The ROW_NUMBER in the ORDER BY clause takes all of the logins for each Employee ID and numbers them by LoginTime with the most recent first (and using the LoginEntry ID as tie breaker, and thanks for that touch, Mat).



Then, the SELECT TOP (1) WITH TIES does its thing. The WITH TIES bit means that it selects the number one result from each PARTITION BY group in the ORDER BY clause.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 22 '18 at 11:21

























answered Nov 22 '18 at 11:13









Eric BrandtEric Brandt

3,28511127




3,28511127













  • The longer and messier one that I didn't show is e JOIN l JOIN (SELECT emp, MAX(time) FROM l). But, I didn't realise SQL Server supported ROW_NUMBER() in the ORDER BY, I'll have to try to remember that. Much tidier :)

    – MatBailie
    Nov 22 '18 at 11:15













  • Oh, eww. But right. I've certainly seen that. I hope I've never written it...

    – Eric Brandt
    Nov 22 '18 at 11:19











  • I started before analytic functions were commonly supported, and have had to use MySQL.

    – MatBailie
    Nov 22 '18 at 11:21











  • I started out using Access97, so there's some (I know now) kludgy code in my past, too. But we work with the tools we have, right?

    – Eric Brandt
    Nov 22 '18 at 11:25



















  • The longer and messier one that I didn't show is e JOIN l JOIN (SELECT emp, MAX(time) FROM l). But, I didn't realise SQL Server supported ROW_NUMBER() in the ORDER BY, I'll have to try to remember that. Much tidier :)

    – MatBailie
    Nov 22 '18 at 11:15













  • Oh, eww. But right. I've certainly seen that. I hope I've never written it...

    – Eric Brandt
    Nov 22 '18 at 11:19











  • I started before analytic functions were commonly supported, and have had to use MySQL.

    – MatBailie
    Nov 22 '18 at 11:21











  • I started out using Access97, so there's some (I know now) kludgy code in my past, too. But we work with the tools we have, right?

    – Eric Brandt
    Nov 22 '18 at 11:25

















The longer and messier one that I didn't show is e JOIN l JOIN (SELECT emp, MAX(time) FROM l). But, I didn't realise SQL Server supported ROW_NUMBER() in the ORDER BY, I'll have to try to remember that. Much tidier :)

– MatBailie
Nov 22 '18 at 11:15







The longer and messier one that I didn't show is e JOIN l JOIN (SELECT emp, MAX(time) FROM l). But, I didn't realise SQL Server supported ROW_NUMBER() in the ORDER BY, I'll have to try to remember that. Much tidier :)

– MatBailie
Nov 22 '18 at 11:15















Oh, eww. But right. I've certainly seen that. I hope I've never written it...

– Eric Brandt
Nov 22 '18 at 11:19





Oh, eww. But right. I've certainly seen that. I hope I've never written it...

– Eric Brandt
Nov 22 '18 at 11:19













I started before analytic functions were commonly supported, and have had to use MySQL.

– MatBailie
Nov 22 '18 at 11:21





I started before analytic functions were commonly supported, and have had to use MySQL.

– MatBailie
Nov 22 '18 at 11:21













I started out using Access97, so there's some (I know now) kludgy code in my past, too. But we work with the tools we have, right?

– Eric Brandt
Nov 22 '18 at 11:25





I started out using Access97, so there's some (I know now) kludgy code in my past, too. But we work with the tools we have, right?

– Eric Brandt
Nov 22 '18 at 11:25











2














you can use window function row_number()



    with cte as(    
SELECT e.ID,l.EmpId,Name,l.LoginTime, row_number() over(partition by e.ID order by l.LoginTime) as rn
FROM Employee e join LoginEntry l on l.EmpId=e.id
) select ID,EmpId,Name,LoginTime from cte where rn=1


demo link






share|improve this answer


























  • Thank You Very much

    – Sreenu131
    Nov 22 '18 at 9:52
















2














you can use window function row_number()



    with cte as(    
SELECT e.ID,l.EmpId,Name,l.LoginTime, row_number() over(partition by e.ID order by l.LoginTime) as rn
FROM Employee e join LoginEntry l on l.EmpId=e.id
) select ID,EmpId,Name,LoginTime from cte where rn=1


demo link






share|improve this answer


























  • Thank You Very much

    – Sreenu131
    Nov 22 '18 at 9:52














2












2








2







you can use window function row_number()



    with cte as(    
SELECT e.ID,l.EmpId,Name,l.LoginTime, row_number() over(partition by e.ID order by l.LoginTime) as rn
FROM Employee e join LoginEntry l on l.EmpId=e.id
) select ID,EmpId,Name,LoginTime from cte where rn=1


demo link






share|improve this answer















you can use window function row_number()



    with cte as(    
SELECT e.ID,l.EmpId,Name,l.LoginTime, row_number() over(partition by e.ID order by l.LoginTime) as rn
FROM Employee e join LoginEntry l on l.EmpId=e.id
) select ID,EmpId,Name,LoginTime from cte where rn=1


demo link







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 22 '18 at 9:52

























answered Nov 22 '18 at 9:50









Zaynul Abadin TuhinZaynul Abadin Tuhin

19.3k31135




19.3k31135













  • Thank You Very much

    – Sreenu131
    Nov 22 '18 at 9:52



















  • Thank You Very much

    – Sreenu131
    Nov 22 '18 at 9:52

















Thank You Very much

– Sreenu131
Nov 22 '18 at 9:52





Thank You Very much

– Sreenu131
Nov 22 '18 at 9:52


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53427881%2fhow-result-using-cross-apply-can-achieve-using-any-other-joins-like-inner-left%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Guess what letter conforming each word

Port of Spain

Run scheduled task as local user group (not BUILTIN)