SQL:基于不匹配数据的相对序列来关联行



所以我确信这可能是一个重复的问题,但我还没能找到正确的答案。正在寻找一个在T-SQL中工作的解决方案。

我试图解决的问题是用松散耦合的数据关联两个表。例如:

CREATE TABLE things1 (
  id INT NOT NULL,
  parentgroup CHAR(1),
  datecreated DATETIME NOT NULL)
GO
INSERT INTO things1
SELECT 1, 'A', '2018-10-01 01:00:00.000'
UNION ALL
SELECT 2, 'A' '2018-10-01 01:00:02.000'
UNION ALL
SELECT 3, 'A', '2018-10-01 01:00:02.345'
UNION ALL
SELECT 4, 'B', '2018-10-01 01:00:01.000'
UNION ALL
SELECT 5, 'B', '2018-10-01 01:00:03.000'
GO
CREATE TABLE things2 (
  id INT NOT NULL,
  parentgroup CHAR(1),
  datecreated DATETIME NOT NULL)
GO
INSERT INTO things2
SELECT 1, 'A', '2018-10-01 01:04:00.000'
UNION ALL
SELECT 2, 'A' '2018-10-01 01:05:12.000'
UNION ALL
SELECT 3, 'A', '2018-10-01 01:05:02.345'
UNION ALL
SELECT 4, 'A', '2018-10-01 01:06:01.000'
UNION ALL
SELECT 5, 'A', '2018-10-01 01:07:03.000'
UNION ALL
SELECT 6, 'B', '2018-10-01 01:04:08.000'
GO

我试图填充的是:

CREATE TABLE things1xthings2 (thing1id INT, thing2id INT)
GO

这两个表中的行需要如何耦合的规则是通过对给定父组的日期创建值进行排序(因此是本文的标题(。对于上面的示例数据,规则将显示为:

thing1id    thing2id
--------    --------
1           1        (matching lowest datecreated for group A)
2           3        (matching next lowest)
3           2        (matching next lowest)
4           6        (matching lowest datecreated for group B)

重要的一点:在任意一个表中,给定的组都可能有更多的行。"临时演员"就是不会有伴侣,也不会在交叉桌上有一排。

我不知道有什么方法可以在基于单个集合的JOIN操作中实现这一点,但如果有办法做到这一点的话,我很乐意看到它

我的方法是在每个表中添加一列:

ALTER TABLE things1 ADD sequence INT
GO
ALTER TABLE things2 ADD sequence INT 
GO

该列实质上将日期创建的值转换为枚举序列,然后可以在基于集合的JOIN操作中进行匹配,以填充交叉表:

INSERT INTO things1xthings2
SELECT t1.id, t2.id
FROM things1 t1 
JOIN things2 t2 ON t2.parentgroup = t1.parentgroup
  AND t2.sequence = t1.sequence

问题是我也不知道如何构建序列列的值。我只知道完成后数据会是这样的:

SELECT * FROM things1
id parentgroup datecreated             sequence
-- ----------- -----------             --------
1  A           2018-10-01 01:00:00.000 1
2  A           2018-10-01 01:00:02.000 2
3  A           2018-10-01 01:00:02.345 3
4  B           2018-10-01 01:00:01.000 1
5  B           2018-10-01 01:00:03.000 2
SELECT * FROM things2
id parentgroup datecreated             sequence
-- ----------- -----------             --------
1  A           2018-10-01 01:04:00.000 1
2  A           2018-10-01 01:05:02.345 2
3  A           2018-10-01 01:05:12.000 3
4  A           2018-10-01 01:06:01.000 4
5  A           2018-10-01 01:07:03.000 5
6  B           2018-10-01 01:04:08.000 1

谢谢你的帮助!

(编辑:我的"f"one_answers"d"键卡住了!(

非常感谢用户@Shnugo为我指明了正确的方向。在OVER子句中使用ROW_NUMBER((和PARTITION BY和ORDER BY,我能够在单个集合操作中创建所需的关联,如下所示:

SELECT a.id, b.id
FROM (
    SELECT id, parentgroup, datecreated, 
        ROW_NUMBER() OVER(
            PARTITION BY parentgroup 
            ORDER BY datecreated) AS seq
    FROM things1) a
JOIN (
    SELECT id, parentgroup, datecreated, 
        ROW_NUMBER() OVER(
            PARTITION BY parentgroup 
            ORDER BY datecreated) AS seq
    FROM things2) b ON b.parentgroup = a.parentgroup 
AND b.seq = a.seq

当对上面的样本数据运行时,它会产生所需的关联:

1<->1
2<->3
3<->2
4<->6

只需添加一个简单的INSERT,就可以完全根据需要填充表。

最新更新