0

My brain refuses to cooperate with me today to actually think this through properly so I was hoping to get some feedback: I want to return a single record from each member for their most recent entrance into the system but so far I obviously have only been able to return a single record for the most recent datetime of any member. I know the query isn't quite right but my brain refuses to really cooperate...

The SQL:

SELECT 
    cm.FNAME, 
    cm.LNAME, 
    cl.entry_access_point, 
    cl.date_entered, 
    cl.res_id, 
    dbo.HourMinuteSecond(cl.date_entered, getUTCDate())[Day:Hour:Minute:Second]
FROM 
    cred.members cm, cred.allocate_log cl
WHERE 
    cm.member_id = cl.member_id AND
    cl.date_exited IS NULL AND 
    cl.evt_id = @eventId AND
    date_entered IN (SELECT max(cl.date_entered)
                     FROM cred.allocate_log cl, cred.members cm
                     WHERE cl.member_id = cm.member_id)
ORDER BY 
    cl.date_entered;
4

3 回答 3

2

进行此类查询的最佳方法是使用row_number(). 此外,您应该学习使用join语法而不是将连接放在where子句中。

select t.*
from (SELECT cm.FNAME, cm.LNAME, cl.entry_access_point, cl.date_entered, cl.res_id, 
             dbo.HourMinuteSecond(cl.date_entered, getUTCDate()) as [Day:Hour:Minute:Second],
             ROW_NUMBER() over (partition by cm.member_id order by cl.date_enetered desc) as seqnum
      FROM cred.members cm join
           cred.allocate_log cl
           on cm.member_id = cl.member_id
      WHERE cl.date_exited IS NULL AND 
            cl.evt_id = @eventId
     ) t
ORDER BY date_entered;
于 2013-06-06T18:26:16.547 回答
1
select 
   those fields
from cred.members cm,
join (
select member_id, max(date_entered) maxdate
from cred.allocate_log
where date_exited is null
and evt_id = @eventId
group by member_id
) s on cm.member_id = s.member_id
join cred.allocate_log cl on
  cm.member_id = cl.member_id
  and cl.date_entered = s.maxdate

您还可以使用非标准CROSS APPLY运算符,如果给定的 date_entered 可能有不止一行,它可以使事情变得更简单

select
   those fields
from cred.members cm
cross apply (
    select top 1
       fields from log
    from cred.allocate_log cl
    where cm.member_id = cl.member_id
    and date_exited is null
    and evt_id = @eventId
    order by date_entered desc
)
于 2013-06-06T18:49:03.997 回答
1

只需在子查询中为 member_id 添加规则:

SELECT 
cm.FNAME, 
cm.LNAME, 
cl.entry_access_point, 
cl.date_entered, 
cl.res_id, 
dbo.HourMinuteSecond(cl.date_entered, getUTCDate())[Day:Hour:Minute:Second]
FROM cred.members cm, cred.allocate_log cl
WHERE cm.member_id = cl.member_id AND
    cl.date_exited IS NULL AND 
    cl.evt_id = @eventId AND
    date_entered IN (
        SELECT max(cl.date_entered)
        FROM cred.allocate_log cl, cred.members cms
        WHERE cl.member_id = cms.member_id and cms.member_id = cm.member_id)
ORDER BY cl.date_entered

但是您还需要在子查询中声明 evt_id,它可以简化如下:

SELECT 
    cm.FNAME, 
    cm.LNAME, 
    cl.entry_access_point, 
    cl.date_entered, 
    cl.res_id, 
    dbo.HourMinuteSecond(cl.date_entered, getUTCDate())[Day:Hour:Minute:Second]
    FROM cred.members cm, cred.allocate_log cl
    WHERE cm.member_id = cl.member_id AND
        cl.date_exited IS NULL AND 
        cl.evt_id = @eventId AND
        date_entered >= ALL (
            SELECT cl.date_entered
            FROM cred.allocate_log cls
            WHERE cls.member_id = cm.member_id AND cls.evt_id = cl.evt_id)
    ORDER BY cl.date_entered

更改子查询中表的别名:

SELECT 
        cm.FNAME, 
        cm.LNAME, 
        cl.entry_access_point, 
        cl.date_entered, 
        cl.res_id, 
        dbo.HourMinuteSecond(cl.date_entered, getUTCDate())[Day:Hour:Minute:Second]
        FROM cred.members cm, cred.allocate_log cl
        WHERE cm.member_id = cl.member_id AND
            cl.date_exited IS NULL AND 
            cl.evt_id = @eventId AND
            date_entered >= ALL (
                SELECT cls.date_entered
                FROM cred.allocate_log cls
                WHERE cls.member_id = cm.member_id AND cls.evt_id = cl.evt_id)
        ORDER BY cl.date_entered
于 2013-06-06T18:49:16.077 回答