【问题标题】:Subquery for Distinct Most Recent Address (Multiple Fields) within Joins连接中不同最近地址(多个字段)的子查询
【发布时间】:2016-08-27 08:36:15
【问题描述】:

我正在尝试检索与名称关联的最新地址(因为每个名称通常有多个地址)。我在我的联接中创建了以下带有子查询的查询。我可以根据需要为每一方撤回一个地址,但地址/城市并不总是匹配,或者返回的地址不是最近的地址(根据相关日期)。我用 MAX 写错了子查询吗?有没有办法确保正确的城市和正确的地址?

select 
    [demographics].[DOB],
    Address1,
    Address2,
    City,
    State,
    Zip

from [demographics]
    left join (select
                    [address].[demographic_ID], 
                    max([address].[address1]) as Address1,
                    max([address].[address2]) as Address2,
                    max([address].[city]) as City,
                    max([states].[state_title]) as 'State',
                    max([dbo].[address].[zip]) as Zip
                from [address]
                    inner join [states] on [address].[state_ID] = [states].[state_ID]
                group by [address].[demographic_ID]) as AddressSub 
        on [demographics].[demographic_ID] = AddressSub.[demographic_ID];

【问题讨论】:

  • 是的,你写错了。考虑一下如何使用 TOP 1 而不是 MAX。
  • 我认为使用 Row_Number over (partition by Address.PK order by Date? ID? [what field determines most recent] desc) 之类的分析会更容易,然后将其限制为 row_number 1。
  • 是的,顺便说一句,您需要有一列来确定哪个地址是最新的,我看不到您的查询中使用了该列。
  • 谢谢你,标签!这样可以将我的地址保持在一起,然后我按“[address1] desc”命令将其与每个日期的最新地址一起提取。

标签: sql tsql join subquery max


【解决方案1】:

在 SQL Server 中解决此问题的一种方法是使用 outer apply(在其他数据库中,这称为“横向连接”)。假设您有一些方法可以确定最近的地址,您可以这样做:

select d.*, a.*
from [demographics] d outer apply
     (select a.*, s.state_title as state
      from address a inner join
           states s
           on a.[state_ID] = s.[state_ID]
      where a.demographic_ID = d.demographic_ID
      order by ?? desc
     ) a;

(我将省略特定列的详细信息。)

?? 代表定义“最近”的列——例如,身份主键或记录创建日期。在这种情况下,outer apply 基本上是一个相关子查询,允许您返回多个列。

注意:我强烈建议使用表别名。它们使查询更易于编写和阅读。

【讨论】:

    【解决方案2】:

    如果您查看子查询,您实际要求的是每个列的最大值(因为这些是字符串按字母顺序排列的最大值)字段。这不太可能从同一地址行返回字段。例如,如果您有两行都与相同的人口统计 ID 相关,其中一个具有 address_1=Z 和 address_2=A,另一行具有 address_1=A 和 address_2=Z,您将返回 Z 和 Z(第一个中的 address_1 和第一个中的 address_2第二)。我认为这不是您的目标。

    首先,如果您有该选项,您可以通过稍微更改数据库来使事情变得更容易一些。您可以在您的人口统计数据中输入一个最新的地址 ID,您可以更新并使用它直接链接到您想要的地址。或者您可以在地址中添加一列来存储创建时间或编辑时间,并使用它来获取最近的时间。

    或者,如果您不想更改数据库,您可以按照上面的建议进行操作,并使用 rownumber 作为地址中最新项目的标识符。您首先需要在子查询中返回人口统计 ID 和最大值(行号),然后在第二个子查询中返回地址的其余详细信息。

    【讨论】:

      【解决方案3】:

      要做到这一点,我需要知道地址表的 PK 以及如何确定“最新”

      SELECT
          [demographics].[DOB],
          Address1,
          Address2,
          City,
          State,
          Zip
      
      FROM [demographics]
      LEFT JOIN (SELECT
                 Row_number() over (partition by Demographic_ID ORDER BY Demographic_ID Desc) RN
                 [address].[demographic_ID], 
                 [address].[address1] as Address1,
                 [address].[address2] as Address2,
                 [address].[city] as City,
                 [states].[state_title] as 'State',
                 [address].[zip] as Zip
                 FROM [address]
                 INNER JOIN [states] 
                    on [address].[state_ID] = [states].[state_ID]
                 GROUP BY [address].[demographic_ID]) as AddressSub 
        on [demographics].[demographic_ID] = AddressSub.[demographic_ID]
       and  AddressSub.RN = 1
      

      【讨论】:

      • 你想用demographic_id分区。
      • 是的,我现在可以在连接中看到。但是还是不知道怎么下单。除非我们假设最高的人口统计 ID 是最近的...
      • 。 .然后,您希望按某种创建日期或主键(如果您知道它是一个标识列)进行排序。
      • 这项工作成功,但按最旧日期而不是最近日期拉动。地址表的 PK 是 Address_ID,但是,不知何故,我必须能够按日期 desc 排序,可能吗?
      • 知道了;在我按 [changed_date] 订购的“row_number”行中,它起作用了!谢谢大家的帮助!
      【解决方案4】:

      最近的应该是地址列中的最后一个条目

      select 
      [demographics].[DOB],
      Address1,
      Address2,
      City,
      State,
      Zip
      
      from [demographics]
      left join (select top 1 max([address.EntryDate)
                      [address].[demographic_ID], 
                      [address].[address1] as Address1,
                      [address].[address2] as Address2,
                      [address].[city] as City,
                      [states].[state_title] as 'State',
                      [dbo].[address].[zip] as Zip
                  from [address]
                      inner join [states] on [address].[state_ID] = [states].[state_ID]
                  group by [address].[demographic_ID], 
                      [address].[address1] as Address1,
                      [address].[address2] as Address2,
                      [address].[city] as City,
                      [states].[state_title] as 'State',
                      [dbo].[address].[zip] as Zip
      
          on [demographics].[demographic_ID] = AddressSub.[demographic_ID];
      

      【讨论】:

        猜你喜欢
        • 2021-08-25
        • 2018-10-20
        • 2012-05-12
        • 2012-04-02
        • 1970-01-01
        • 1970-01-01
        • 2011-01-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多