【问题标题】:SQL query to return collated results based upon two columns基于两列返回整理结果的 SQL 查询
【发布时间】:2018-05-17 03:35:47
【问题描述】:

假设我有一个包含以下列的表格:

Id,   ConnectionId,  File,      FileCreated
int,     int,       varchar,     DateTime

数据示例

进一步,假设它充满了未排序的数据,如下所示:

    1, 3, "a.dat", 2018-05-16 13:53:40.008
    2, 1, "b.dat", 2018-05-16 13:53:40.007
    3, 3, "c.dat", 2018-05-16 13:53:40.009
    4, 3, "z.dat", 2018-05-16 13:53:40.002
    5, 3, "h.dat", 2018-05-16 13:53:40.003
    6, 2, "ba.dat", 2018-05-16 13:53:40.004
    7, 3, "zy.dat", 2018-05-16 13:53:40.005
    8, 1, "f.dat", 2018-05-16 13:53:40.001
    9, 1, "cd.dat", 2018-05-16 13:53:40.006

我如何查询这些数据以便数据集返回我:

  1. 每个连接一行
  2. 按时间升序排列

预期结果

我正在寻找的结果如下:

注意:我将这些分组,以便您可以看到它们是根据 ConnectionId 首先返回的(例如 group by 也许)。

8, 1, "f.dat", 2018-05-16 13:53:40.001
4, 3, "z.dat", 2018-05-16 13:53:40.002
6, 2, "ba.dat", 2018-05-16 13:53:40.004

5, 3, "h.dat", 2018-05-16 13:53:40.003
9, 1, "cd.dat", 2018-05-16 13:53:40.006

7, 3, "zy.dat", 2018-05-16 13:53:40.005
2, 1, "b.dat", 2018-05-16 13:53:40.007

1, 3, "a.dat", 2018-05-16 13:53:40.008
3, 3, "c.dat", 2018-05-16 13:53:40.009

希望我的示例向您展示了这些不是严格基于时间的,也不是严格基于 connectionId 的。两者都是。

【问题讨论】:

  • 我被你的措辞吓到了。每个连接只需要一行吗? connectionID 是否唯一标识了一个连接? (如果没有,请务必更改该名称)。如果是这样,这与预期结果不符。
  • 是的,ConnectionId 确实唯一标识了连接。这是表的外键,在实际解决方案中该表还有更多内容,但试图保持简单。我希望最终结果看起来就像我的结果示例中返回的所有行。意思是很多行,但按 connectionid 分组——但我的语言仍然不能很好地解释。 :|

标签: sql sql-server tsql


【解决方案1】:

这样试试

DECLARE @mockup TABLE(Id INT,ConnectionId INT,[File] VARCHAR(100),FileCreated DATETIME2);
INSERT INTO @mockup VALUES
 (1, 3, 'a.dat','2018-05-16T13:53:40.008')
,(2, 1, 'b.dat','2018-05-16T13:53:40.007')
,(3, 3, 'c.dat','2018-05-16T13:53:40.009')
,(4, 3, 'z.dat','2018-05-16T13:53:40.002')
,(5, 3, 'h.dat','2018-05-16T13:53:40.003')
,(6, 2, 'ba.dat','2018-05-16T13:53:40.004')
,(7, 3, 'zy.dat','2018-05-16T13:53:40.005')
,(8, 1, 'f.dat','2018-05-16T13:53:40.001')
,(9, 1, 'cd.dat','2018-05-16T13:53:40.006');

SELECT *
FROM @mockup
ORDER BY ROW_NUMBER() OVER(PARTITION BY ConnectionId ORDER BY FileCreated)
        ,FileCreated;

编辑这个很好的答案以添加结果(并将 DateTime 更新为 DateTime2): 太棒了——结果完全符合我的预期。

Id  ConnectionId    File    FileCreated
8   1              f.dat    2018-05-16 13:53:40.0010000
4   3              z.dat    2018-05-16 13:53:40.0020000
6   2              ba.dat   2018-05-16 13:53:40.0040000
5   3              h.dat    2018-05-16 13:53:40.0030000
9   1              cd.dat   2018-05-16 13:53:40.0060000
7   3              zy.dat   2018-05-16 13:53:40.0050000
2   1              b.dat    2018-05-16 13:53:40.0070000
1   3              a.dat    2018-05-16 13:53:40.0080000
3   3              c.dat    2018-05-16 13:53:40.0090000

【讨论】:

  • 谢谢,非常好的答案和有用的临时/模拟表帮助我实际尝试。你只是比其他答案稍晚。
  • @raddevus 是的,因为模拟:-D
  • 我编辑了您的出色答案以显示结果。并添加与结果相关的这个问题。我注意到 FileCreated 时间就像按时间分组一样。这不是与原始行关联的实际 FileCreated。这不会真正影响我的解决方案,但它很有趣。
  • @raddevus,有趣的观察!将DATETIME 更改为DATETIME2,您将看到预期值。这是由于DATETIME 的粒度造成的。
【解决方案2】:

您可以在order by 子句中使用row_number()

select t.*
from t
order by row_number() over (partition by connectionId order by fileCreated),
         fileCreated;

【讨论】:

  • 效果很好。我永远不会找到这个答案,因为我不知道 row_number() over partition 等。我将进一步分解它以理解它,但这似乎正是我想要的。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-01
相关资源
最近更新 更多