【问题标题】:How to join two tables based on FIRST VALUE of a group如何根据组的第一个值连接两个表
【发布时间】:2019-01-29 17:32:38
【问题描述】:

目标:我想根据 Id 列的第一个值加入两个表,该列按按 created_at 列排序的订阅 Id 列分组。

情况:

Table1 如下所示:

id  channel trx_date
123 organic 01/01/2019 05:00:00
234 direct  01/01/2019 05:01:00
987 add     01/01/2019 10:00:00
654 organic 01/01/2019 10:15:00

表2:

subscription_id id  os      created_at
sub890         123  mac     01/01/2019 05:00:01
sub890         234  mac     01/01/2019 05:01:01
sub111         987  windows 01/01/2019 10:00:01
sub111         654  mac     01/01/2019 10:20:01

我需要取表 2 中按订阅 ID 分组的最早 ID,并将其与表 1 内联。 所以在这个例子中,我的输出是

subscription_id id  os      created_at id       channel trx_date
sub890          123 mac     01/01/2019 05:00:01 organic 01/01/2019 05:00:00
sub111          987 windows 01/01/2019 10:00:01 add     01/01/2019 10:00:00

我尝试了什么:我考虑过使用 FIRST_VALUE,但我不知道如何连接它们

SELECT t1.*, 
  t2.subscription_id,
  t2.os,
  t2.created_at, 
  FIRST_VALUE(t2.id) OVER (PARTITION BY t2.subscription_id ORDER BY t2.created_at ASC) as Min_Id
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.Min_id

小提琴信息:

CREATE TABLE table1
    ([id] varchar(13), [channel] varchar(50), [trx_date] Datetime)


INSERT INTO table1
VALUES
    ('123', 'organic', '2019-01-01 05:00:00'),
    ('234', 'direct', '2019-01-01 05:01:00'),
    ('987', 'add', '2019-01-01 10:00:00'),
    ('654', 'organic', '2019-01-01 10:15:00')

CREATE TABLE table2
    ([subscription_id] varchar(13),[id] varchar(13), [os] varchar(10), [created_at] Datetime)

INSERT INTO table2
VALUES
    ('sub890', '123', 'mac', '2019-01-01 05:00:01'),
    ('sub890', '234', 'mac', '2019-01-01 05:01:01'),
    ('sub111', '987', 'windows', '2019-01-01 10:00:01'),
    ('sub111', '654', 'mac', '2019-01-01 10:20:01')

显然,由于 ON 子句,这不起作用。这种情况是否需要一个带有交叉应用的 row_number 函数?有没有更好的方法来做到这一点? FIRST_VALUE 是不是用错了函数?

【问题讨论】:

    标签: sql sql-server inner-join partitioning


    【解决方案1】:

    您可以使用 row_number() 并按 create_at 日期订购,这将采用第一个 id

    with cte as
    (
    select *,row_number() over(partition by subscription_id  order by created_at) rn
      from tabl2
    ) select cte.*,t1.* from cte 
           join table1 t1 on cte.id =t1.id
      where cte.rn=1
    

    demo link

    subscription_id id  os    created_at           rn   id  channel  trx_date
    sub890          123 mac   01/01/2019 05:00:01   1   123 organic 01/01/2019 05:00:00
    sub111          987 windows 01/01/2019 10:00:01 1   987 add     01/01/2019 10:00:00
    

    【讨论】:

    • 就性能而言,这会比上面提出的交叉应用更有效吗?
    • @RogerSteinberg 你可以检查哪一个提供更好的性能
    【解决方案2】:

    applytop (1) 一起使用:

    SELECT t1.*, t2.subscription_id, t2.id, t2.os, t2.created_at
    FROM table1 t1 CROSS APPLY
         (SELECT TOP (1) t2.*
          FROM table2 t2 
          WHERE t1.id = t2.id
          ORDER BY t2.created_at ASC
         ) t2
    

    【讨论】:

    • 。 . .你错过了top (n) 子句。
    • @YogeshSharma 。 . .谢谢。
    • @GordonLinoff 有关 Min_id 的错误:列名“Min_id”无效
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 2018-05-05
    • 2021-11-17
    • 2015-12-15
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多