Sql 获取具有交集的元组

Sql 获取具有交集的元组,sql,google-bigquery,Sql,Google Bigquery,我有两列定义一个人——passport\u id和driver\u license\u id。passport\u id和driver\u license\u id是唯一定义这个人的 目前,只有一种唯一的passport\u id+driver\u license\u id组合。但一个人可以有多个passport\u id和多个driver\u license\u id 有一个包含这两列的表,其中包含所有组合: passport_id | driver_license_id 111

我有两列定义一个人——passport\u id和driver\u license\u id。passport\u id和driver\u license\u id是唯一定义这个人的

目前,只有一种唯一的passport\u id+driver\u license\u id组合。但一个人可以有多个passport\u id和多个driver\u license\u id

有一个包含这两列的表,其中包含所有组合:

passport_id | driver_license_id
111         | aaa
222         | aaa
333         | bbb
111         | bbb
如何为每个护照id和驾照id获取唯一的个人id


对于上面的示例,它是一个人,因为111对应于aaa和bbb,这意味着这个人有3个passport\u id和2个driver\u license\u id。

下面的示例是针对带有脚本的BigQuery标准SQL

#standardSQL
DECLARE rows_count, run_away_stop INT64 DEFAULT 0;

CREATE TEMP TABLE input AS (
  select '111' passport_id, 'aaa' driver_license_id union all
  select '222', 'aaa' union all
  select '333', 'bbb' union all
  select '111', 'bbb' union all
  select '444', 'ccc' union all
  select '444', 'ddd' union all
  select '555', 'ddd' union all
  select '666', 'eee' union all
  select '777', 'fff' 
);

CREATE TEMP TABLE initial_grouping AS 
SELECT ARRAY_AGG(driver_license_id ORDER BY driver_license_id) arr 
FROM input
GROUP BY passport_id;

LOOP
  SET rows_count = (SELECT COUNT(1) FROM initial_grouping);
  SET run_away_stop = run_away_stop + 1;

  CREATE OR REPLACE TEMP TABLE initial_grouping AS
  SELECT ANY_VALUE(arr) arr FROM (
    SELECT ARRAY(SELECT DISTINCT val FROM UNNEST(arr) val ORDER BY val) arr
    FROM (
      SELECT ANY_VALUE(arr1) arr1, ARRAY_CONCAT_AGG(arr) arr    
      FROM (
        SELECT t1.arr arr1, t2.arr arr2, ARRAY(SELECT DISTINCT val FROM UNNEST(ARRAY_CONCAT( t1.arr, t2.arr)) val ORDER BY val) arr 
        FROM initial_grouping t1, initial_grouping t2 
        WHERE (SELECT COUNT(1) FROM UNNEST(t1.arr) val JOIN UNNEST(t2.arr) val USING(val)) > 0
      ) GROUP BY FORMAT('%t', arr1)
    )
  ) GROUP BY FORMAT('%t', arr);

  IF (rows_count = (SELECT COUNT(1) FROM initial_grouping) AND run_away_stop > 1) OR run_away_stop > 10 THEN BREAK; END IF;
END LOOP;

SELECT passport_id, driver_license_id, final_grouping FROM input 
JOIN (SELECT ROW_NUMBER() OVER() final_grouping, arr FROM initial_grouping) 
ON driver_license_id IN UNNEST(arr) 
ORDER BY passport_id, driver_license_id; 
有输出

要将上述示例应用于实际数据,请删除
CREATE TEMP TABLE input(…)
语句,并将
CREATE TEMP TABLE initial\u分组中的
input
替换为…
语句,并参考实际表
project.dataset.TABLE


此外,请确保为run\u away\u stop设置了适当的最大值(在上面的脚本中,它是
10
-请参阅循环中的最后一条语句-您可能需要增加它以确保转换将完成)

下面的示例适用于带有脚本的BigQuery标准SQL

#standardSQL
DECLARE rows_count, run_away_stop INT64 DEFAULT 0;

CREATE TEMP TABLE input AS (
  select '111' passport_id, 'aaa' driver_license_id union all
  select '222', 'aaa' union all
  select '333', 'bbb' union all
  select '111', 'bbb' union all
  select '444', 'ccc' union all
  select '444', 'ddd' union all
  select '555', 'ddd' union all
  select '666', 'eee' union all
  select '777', 'fff' 
);

CREATE TEMP TABLE initial_grouping AS 
SELECT ARRAY_AGG(driver_license_id ORDER BY driver_license_id) arr 
FROM input
GROUP BY passport_id;

LOOP
  SET rows_count = (SELECT COUNT(1) FROM initial_grouping);
  SET run_away_stop = run_away_stop + 1;

  CREATE OR REPLACE TEMP TABLE initial_grouping AS
  SELECT ANY_VALUE(arr) arr FROM (
    SELECT ARRAY(SELECT DISTINCT val FROM UNNEST(arr) val ORDER BY val) arr
    FROM (
      SELECT ANY_VALUE(arr1) arr1, ARRAY_CONCAT_AGG(arr) arr    
      FROM (
        SELECT t1.arr arr1, t2.arr arr2, ARRAY(SELECT DISTINCT val FROM UNNEST(ARRAY_CONCAT( t1.arr, t2.arr)) val ORDER BY val) arr 
        FROM initial_grouping t1, initial_grouping t2 
        WHERE (SELECT COUNT(1) FROM UNNEST(t1.arr) val JOIN UNNEST(t2.arr) val USING(val)) > 0
      ) GROUP BY FORMAT('%t', arr1)
    )
  ) GROUP BY FORMAT('%t', arr);

  IF (rows_count = (SELECT COUNT(1) FROM initial_grouping) AND run_away_stop > 1) OR run_away_stop > 10 THEN BREAK; END IF;
END LOOP;

SELECT passport_id, driver_license_id, final_grouping FROM input 
JOIN (SELECT ROW_NUMBER() OVER() final_grouping, arr FROM initial_grouping) 
ON driver_license_id IN UNNEST(arr) 
ORDER BY passport_id, driver_license_id; 
有输出

要将上述示例应用于实际数据,请删除
CREATE TEMP TABLE input(…)
语句,并将
CREATE TEMP TABLE initial\u分组中的
input
替换为…
语句,并参考实际表
project.dataset.TABLE


此外,请确保您为run\u away\u stop设置了适当的最大值(在上面的脚本中,它是
10
-请参阅循环中的最后一条语句-您可能需要增加它以确保转换将完成)

(1)如何识别“人”?(2) 你想要什么结果?@GordonLinoff任何护照id和驾驶执照id都可以唯一识别此人。我想通过将所有护照id和驾驶执照id进行交叉,获得每个护照id和驾驶执照id的个人id。在我的例子中,它应该是一个人的id,例如1(1)你如何识别“人”?(2) 你想要什么结果?@GordonLinoff任何护照id和驾驶执照id都可以唯一识别此人。我想通过将所有护照id和驾驶执照id进行交叉,获得每个护照id和驾驶执照id的个人id。对于我的示例,它应该是一个人的id,例如1