【问题标题】:Subquery to return multiple columns from newest record?子查询从最新记录返回多列?
【发布时间】:2017-10-18 05:41:59
【问题描述】:

我有一个这样的表结构:

文档

ID  | NAME  | DATA
----+-------+--------
1   | Doc1  | Data1
2   | Doc2  | Data2

历史

HID | DOC_ID    | HDATA1    | HDATA2    | HDATA3
----+-----------+-----------+-----------+---------
1   | 1         | A         | B         | C
2   | 2         | C         | D         | E
3   | 1         | A         | A         | B
4   | 1         | B         | B         | D
5   | 2         | E         | A         | C

我希望得到的输出是 HISTORY (最高 HID)中与相应 ID 匹配的字段 NAMEDATAHDATA1HDATA2HDATA3Documents 表。

我发现的示例只从一列返回一个值,但我需要来自多列的数据。我不知道如何设置这个 SQL。

【问题讨论】:

  • 你的问题不清楚。请分享您想要的输出。
  • 更新问题使其更清晰

标签: sql sql-server subquery multiple-columns


【解决方案1】:

以下示例适用于 Oracle,可能会稍微适应不同的 SQL 方言:

SELECT * 
  FROM ( SELECT h.*,
                d.*,
                RANK() OVER (PARTITION BY h.DOC_ID ORDER BY h.HID DESC) AS RNK
           FROM History h
           JOIN Document d ON d.ID = h.DOC_ID )
 WHERE RNK = 1

用以下数据测试:

INSERT INTO Document VALUES ( 1   , 'Doc1'  , 'Data1' );
INSERT INTO Document VALUES ( 2   , 'Doc2'  , 'Data2' );

INSERT INTO History VALUES ( 1   , 1         , 'A'         , 'B'         , 'C' );
INSERT INTO History VALUES ( 2   , 2         , 'C'         , 'D'         , 'E' );
INSERT INTO History VALUES ( 3   , 1         , 'A'         , 'A'         , 'B' );
INSERT INTO History VALUES ( 4   , 1         , 'B'         , 'B'         , 'D' );
INSERT INTO History VALUES ( 5   , 2         , 'E'         , 'A'         , 'C' );

结果:

HID     DOC_ID HDATA1     HDATA2     HDATA3             ID NAME       DATA              RNK
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
         4          1 B          B          D                   1 Doc1       Data1               1 
         5          2 E          A          C                   2 Doc2       Data2               1

【讨论】:

  • @Lars - 你不需要子查询。看我的回答。
【解决方案2】:

使用排序子句中的窗口函数row_numberTOP 1 with ties 结合使用,有一种非常优雅的方法。不需要子查询。

select top 1 with ties *
from document d
join history h
    d.id = h.doc_id
order by row_number() over (
            partition by d.id
            order by h.hid desc
            );

它为每个文档返回一条具有最新历史 ID 的记录。

【讨论】:

    【解决方案3】:

    以下查询将返回每个文档 ID 的最新记录

       SELECT 
                ID, Name, DATA, HDATA1, HDATA2, HDATA3 
       FROM Document D CROSS APPLY (SELECT TOP 1 HDATA1, HDATA2, HDATA3 FROM History H WHERE D.ID=H.DOC_ID ORDER BY H.HID DESC) A
    

    在这种情况下使用交叉应用查询成本会相对较低。 它可以在查询估计的执行计划中显示最佳结果。

    【讨论】:

      【解决方案4】:
      select * from Document d
      inner join (
                  select h1.* from  History h1
                  inner join (
                               select max(hid) as hid from History group by doc_id 
                              ) h2
                  on h1.hid = h2.hid
                 ) t
      on t.doc_id = d.doc_id 
      

      【讨论】:

      • 谢谢jophab。我刚试过这个,历史表中的值不包含在结果中
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多