【问题标题】:SQL - Joining same tableSQL - 加入同一张表
【发布时间】:2013-03-12 17:33:12
【问题描述】:

假设我有一个表 Applications 如下

ApplicationId INT,
CustomerId INT,
ApplicationDate DATETIME,
IsNewCustomer BOOL

我想检索给定日期的应用程序列表以及 IsNewCustomer 标志(如果给定的 CustomerId 没有应用程序,则设置该标志。

目前我在同一张表上使用如下连接

select 
    o.ApplicationId as ApplicationId,
    cast(o.ApplicationDate as date) as ApplicationDate,
    case when n.ApplicationID is not null then 1 else 0 end as IsNewCustomer,
    row_number() over (partition by o.ApplicationId order by o.ApplicationDate desc) as AppSeqNum
from 
    Applications o 
    left join Applications n 
        on n.CustomerId = o.CustomerId
        and n.ApplicationDate < o.ApplicationDate
where
    AppSeqNum = 1
    and ApplicationDate = getdate()

我想知道是否有更好的方法来实现相同的目标,而不必加入同一张桌子,因为它“感觉”不是最优雅的解决方案。

谢谢!

【问题讨论】:

  • 你可以做一个子选择而不是加入同一个表,但它可能会花费更多。我不明白为什么你认为它感觉不对。包含您需要查询的信息的表是 Applications 表,那么查询它有什么问题?另一种选择是将 IsNewCustomer 更新为此表中插入/更新过程的一部分,以便在您需要时准备好数据。
  • 不,你这样做是正确的。这是使用自联接的正确位置。不要让自我加入让你变得不自觉!
  • 如果不对查询进行逆向工程或查看示例数据和所需结果,很难知道,但在 SQL Server 2012 中,使用新的窗口函数可能会有更有效的方法来执行此操作。在早期版本中,这可能是您将要做的最好的事情。表中有多少行?每个客户平均有多少行?
  • 除非您有单独的 Customer 表进行比较,否则我看不出如何按照您描述的方式设置 IsNewCustomer 标志。
  • 感谢你们的 cmets 伙计们,我必须补充一点,我是 SQL 新手,因此不确定“最佳实践”,并认为可能有更优雅的方式来实现这一点。 @tucaz 我同意在插入过程中控制 IsNewCustomer 标志会容易得多,但其他人拥有它,我只是生成报告:)

标签: sql sql-server join


【解决方案1】:

好吧,您可以使用子查询,但这只会掩盖您的自联接。自联接本质上没有任何问题,如果您没有正确的索引和约束并且表大小有限,它们可能会失控。您可能听说自联接不好的原因之一是在其他连续单调序列中寻找中断的问题。假设您有一千个值,其中缺少 5 个,并且您在 value = value +1 上进行了自联接(没有索引或约束),那么查询优化器很可能会在尝试找到 5 之前确定有 1000*1000 个可能的行空匹配。因此,如果您的结果集相当有限,那么没问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-16
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 2018-07-21
    • 1970-01-01
    • 2022-07-06
    • 1970-01-01
    相关资源
    最近更新 更多