【问题标题】:Sql Query : Next Last RowsSql 查询:下一个最后一行
【发布时间】:2017-07-17 08:06:30
【问题描述】:

我有这样的表 CustomerCalls

客户表:

  • CustomerId:唯一标识符
  • 企业名称:nvarchar(MAX)

来电表:

  • CallId:唯一标识符
  • 呼叫日期:日期时间
  • 客户 ID:唯一标识符
  • 状态:int(呼叫已接听或未接听)

我想获取所有带有最后一次调用和下一次调用列的客户。

Last Called 是状态 = 1 的最后一次调用。Next Call 是状态 = 0 和 Calldate > now 日期的调用。如果他们没有,则为 Null。这是一个非工作示例,只是为了显示格式

Select * 
From Customers,
       Calls.CallId as LastCalledId   
       Calls.CallDate as LastCalledDate
       Calls.CallId as NextCallId
       Calls.CallDate as NextCallDate
LEFT JOIN 
    Calls ON Customers.CustomerId = Calls.CustomerId

我该怎么做?

【问题讨论】:

  • 您使用的是什么版本的 sql server?另外,您能否提供 DDL+DML 形式的示例数据和所需的结果?
  • 2008.但是如果有 2008 没有的更简单的解决方案,我们可能会在以后升级。所以如果你能用两种方法告诉我。
  • 我更新了。如果您需要更多信息,请告诉我。

标签: sql sql-server tsql


【解决方案1】:

这是你的意思吗?

更新

select c.id
, lastcall.calldate
, lastcall.id
, firstcall.calldate
, firstcall.id
from @customers c
outer apply (select top 1 calls.calldate, calls.id from @calls calls where calls.custid = c.id and calldate < getdate() order by calldate desc) lastcall(calldate, id)
outer apply (select top 1 calls.calldate, calls.id from @calls calls where calls.custid = c.id and calldate >= getdate() order by calldate asc) firstcall(calldate, id)

原答案:

select c.id
, answered.calldate LastCalledDate
, answered.id LastCalledID
, unaswered.calldate NextCalledDate
, unaswered.id NextCalledID
from @customers c
left join @calls answered ON answered.custid = c.id AND status = 1
left join @calls unaswered ON unaswered.custid = c.id AND unaswered.status = 0 and unaswered.calldate > getdate()

【讨论】:

  • 这个查询可能返回很多结果。我只想要第一个>今天的日期和最后一个
  • @MissakBoyajian 看到更新,还不是很清楚,但我想这就是你的意思。
  • 我从未使用过外部应用,所以请给我时间阅读并测试它:)谢谢,我会回来的
  • 我担心性能。外部应用是最好的解决方案还是可以有更好的解决方案?
  • @MissakBoyajian 执行计划是否建议任何索引?
【解决方案2】:

您可以使用 LEFT JOIN 中的 WHERE 子句来获取所需的数据行。在这里您可以使用 Calls.status = 0 或 1 的 where 子句(根据您的要求)

【讨论】:

    【解决方案3】:

    由于您没有为示例数据提供 DDL 和 DML,我无法测试我的答案,因此不能保证会产生预期的结果。
    话虽如此,这是我的尝试,应该适用于 2008 或更高版本。

    使用 cte 计算每个客户的最后一次接听电话(假设 calldate 是唯一的)和几个左连接我想出了这个:

    ;WITH LastCall AS
    (
        SELECT  CustomerId,
                CallId,
                CallDate
        FROM Calls t0
        WHERE [Status] = 1
        AND CallDate = 
        (
            SELECT MAX(CallDate)
            FROM Calls t1
            WHERE [Status] = 1
            AND t1.CustomerId = t0.CustomerId
        )
    )
    
    SELECT  cu.CustomerId, 
            cu.Name,
            lc.CallId as LastCalledId,
            lc.CallDate as LastCalledDate,
            nc.CallId as NextCallId,
            nc.CallDate as NextCallDate
    FROM Customers as cu
    LEFT JOIN LastCall lc ON cu.CustomerId = lc.CustomerId 
    LEFT JOIN Calls nc ON cu.CustomerId = nc.CustomerId AND nc[Status] = 0 AND nc.CallDate > GETDATE()
    

    请注意,对于 2012 及更高版本,您可能可以使用 FIRST_VALUELAST_VALUE 内置函数。

    【讨论】:

      【解决方案4】:

      您可以在连接查询中使用AND。然后订购电话并获得最后一个有限制的电话。

      SELECT * 
      FROM Customers,
             Calls.CallId as LastCalledId   
             Calls.CallDate as LastCalledDate
             Calls.CallId as NextCallId
      LEFT JOIN 
          Calls ON (Customers.CustomerId = Calls.CustomerId AND Calls.Status = 1)
      ORDER BY Calls.CallDate DESC
      UNION
      SELECT * 
      FROM Customers,
             Calls.CallId as LastCalledId   
             Calls.CallId as NextCallId
             Calls.CallDate as NextCallDate
      LEFT JOIN 
          Calls ON (Customers.CustomerId = Calls.CustomerId AND Calls.Status = 0 AND CallDate > NOW())
      ORDER BY Calls.CallDate DESC;
      

      【讨论】:

      • 我觉得这里的next和Last是一样的
      • 我认为这会返回 1 个客户
      • 删除TOP 1可以获得所有客户。 @MissakBoyajian
      【解决方案5】:

      您可以使用不同的方式来做到这一点:

          Select cu.CustomerId,LastCall.Callid,LastCall.calldate,NextCall.Callid,NextCall.calldate from Customers cu,
          (select max(callid) Callid,max(calldate) calldate,CustomerId from Calls c where status = 1 group by CustomerId) LastCall,
          (select max(callid) Callid,max(calldate) calldate,CustomerId from Calls c where status = 0 and calldate > sysdate group by CustomerId) NextCall
          where cu.CustomerId = LastCall.CustomerId and cu.CustomerId = NextCall.CustomerId
          order by 1
      
      Or by replacing in your query :
      
          Select (select max(callid) from Calls c where c.CustomerId = Cu.CustomerId and status = 1) as LastCalledId,
             (select max(CallDate) from Calls c where c.callid = (select max(callid) from Calls c where c.CustomerId = Cu.CustomerId and status = 1)) as LastCalledDate,
             (select max(callid) from Calls c where c.CustomerId = Cu.CustomerId and status = 0 and CallDate > sysdate ) as NextCallId,
             (select max(CallDate) from Calls c where c.callid = (select max(callid) from Calls c where c.CustomerId = Cu.CustomerId and status = 0 and CallDate > sysdate )) as NextCallDate 
          From Customers Cu,Calls c ON Cu.CustomerId = c.CustomerId
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-21
        • 1970-01-01
        相关资源
        最近更新 更多