我正在尝试创建一个组ID,其中表中两列的值与另一行的两列中的任一值匹配。例如:
表:
+---------+-------------------+
| ogr_fid | comapared_ogr_fid |
+---------+-------------------+
| 8 | 10 |
| 6 | 8 |
| 10 | 4 |
| 5 | 3 |
| 5 | 2 |
| 12 | 15 |
+---------+-------------------+
理想输出:
+---------+-------------------+-------+
| ogr_fid | comapared_ogr_fid | SP_ID |
+---------+-------------------+-------+
| 8 | 10 | 1 |
| 6 | 8 | 1 |
| 10 | 4 | 1 |
| 5 | 3 | 2 |
| 5 | 2 | 2 |
| 12 | 15 | 3 |
+---------+-------------------+-------+
有关如何实现这一目标的任何想法?我一直在尝试使用光标。以下是我的代码。它似乎工作,但返回重复。注释掉的代码不起作用,它返回错误:
警告:聚合或其他SET操作消除了空值。
IF OBJECT_ID('SpatialAggregation.dbo.zzzInitialStack') IS NOT NULL -- Drop temp table if exists
DROP TABLE dbo.zzzInitialStack;
GO
CREATE TABLE dbo.zzzInitialStack
(
SP_ID int,
ogr_fid int,
compared_ogr_fid int
)
GO
IF OBJECT_ID('tempdb.dbo.#Stack') IS NOT NULL
DROP TABLE #Stack
;
SELECT ogr_fid
,compared_ogr_fid
INTO #Stack
FROM dbo.zzzCentroidCalc
WHERE CentroidDistance < 20 AND AvgScore >= 0.70 AND ogr_fid IS NOT NULL AND compared_ogr_fid IS NOT NULL
-- Declare Initial Variables
DECLARE @ogr_fid int, @compared_ogr_fid int, @sp_id int, @sp int, @in_grp int
-- set SP ID group to 1
SET @sp_id = 1
-- create Cursor
DECLARE sp_cursor CURSOR FOR
SELECT ogr_fid
,compared_ogr_fid
FROM #Stack
ORDER BY ogr_fid, compared_ogr_fid
OPEN sp_cursor
--Select next row from cursor
FETCH NEXT FROM sp_cursor
INTO @ogr_fid, @compared_ogr_fid
WHILE @@FETCH_STATUS = 0
--Start Stacked Parcel grouping
BEGIN
--IF (SELECT COUNT(*) FROM dbo.zzzInitialStack) IS NULL
-- BEGIN
-- INSERT INTO dbo.zzzInitialStack (SP_ID, ogr_fid,compared_ogr_fid)
-- VALUES(@sp_id,@ogr_fid,@compare_ogr_fid)
-- SET @sp_id = @sp_id + 1
-- END
--ELSE IF (SELECT count(*) FROM dbo.zzzInitialStack WHERE @ogr_fid = ogr_fid) IS NOT NULL
-- BEGIN
-- SET @sp = (SELECT MAX(SP_ID) FROM dbo.zzzInitialStack WHERE @ogr_fid = ogr_fid)
-- INSERT INTO dbo.zzzInitialStack(SP_ID, ogr_fid,compared_ogr_fid)
-- VALUES(@sp,@ogr_fid,@compare_ogr_fid)
-- END
--ELSE IF (SELECT COUNT(*) FROM dbo.zzzInitialStack WHERE @compared_ogr_fid = ogr_fid) IS NOT NULL
-- BEGIN
-- SET @sp = (SELECT MAX(SP_ID) FROM dbo.zzzInitialStack WHERE @compared_ogr_fid = ogr_fid)
-- INSERT INTO dbo.zzzInitialStack(SP_ID, ogr_fid,compared_ogr_fid)
-- VALUES(@sp,@ogr_fid,@compared_ogr_fid)
-- END
--ELSE
-- BEGIN
-- INSERT INTO dbo.zzzInitialStack(SP_ID, ogr_fid, compared_ogr_fid)
-- VALUES(@sp_id,@ogr_fid,@compared_ogr_fid)
-- SET @sp_id = @sp_id + 1
-- END
INSERT INTO dbo.zzzInitialStack (SP_ID,ogr_fid,compared_ogr_fid)
SELECT CASE WHEN @ogr_fid IN (SELECT ogr_fid FROM dbo.zzzInitialStack) OR @ogr_fid IN (SELECT ogr_fid FROM dbo.zzzInitialStack)
OR @compared_ogr_fid IN (SELECT ogr_fid FROM dbo.zzzInitialStack) OR @compared_ogr_fid IN (SELECT ogr_fid FROM dbo.zzzInitialStack)
THEN (SELECT TOP 1 SP_ID FROM dbo.zzzInitialStack
WHERE @ogr_fid = ogr_fid OR @ogr_fid = compared_ogr_fid
OR @compared_ogr_fid = ogr_fid OR @compared_ogr_fid = compared_ogr_fid)
ELSE (SELECT CASE WHEN MAX(SP_ID) IS NULL
THEN 1
ELSE CAST(MAX(SP_ID) + 1 AS INT)
END
FROM dbo.zzzInitialStack)
END AS SP_ID
,@ogr_fid AS ogr_fid
,@compared_ogr_fid AS compared_ogr_fid
FETCH NEXT FROM sp_cursor INTO @ogr_fid, @compared_ogr_fid
END;
CLOSE sp_cursor;
DEALLOCATE sp_cursor;
GO
IF OBJECT_ID('dbo.StackedParcels') IS NOT NULL
DROP TABLE dbo.StackedParcels;
WITH cte1 AS (
SELECT DISTINCT SP_ID, ogr_fid
FROM dbo.zzzInitialStack
UNION ALL
SELECT DISTINCT SP_ID, compared_ogr_fid AS ogr_fid
FROM dbo.zzzInitialStack
)
,cte2 AS (
SELECT SP_ID, count(ogr_fid) AS NumParcels
FROM cte1
GROUP BY SP_ID
)
SELECT a.SP_ID
,b.ogr_fid
,a.NumParcels
INTO dbo.StackedParcels
FROM cte2 AS a JOIN cte1 AS b ON a.SP_ID = b.SP_ID
答案 0 :(得分:1)
奇怪的是,我最近才解决了very similar problem。所以我基本上使用了我在那里给出的解决方案,调整到你的数据字段。
请注意,此脚本不处理NULL
值。如果源表中包含NULL
值,请在生成集ID之前将其替换为INT(-2147483648)的最小值。使用NULLIF
在最终NULL
语句中将其替换为SELECT
。
SET NOCOUNT ON;
CREATE TABLE #id(ID INT IDENTITY(1,1) PRIMARY KEY,ogr_fid INT,comapared_ogr_fid INT);
INSERT INTO #id(ogr_fid,comapared_ogr_fid) VALUES
(8,10),
(6,8),
(10,4),
(5,3),
(5,2),
(12,15);
CREATE TABLE #sets(set_id INT,fid INT PRIMARY KEY);
DECLARE c_id CURSOR FAST_FORWARD FOR
SELECT ogr_fid,comapared_ogr_fid FROM #id;
OPEN c_id;
DECLARE @ogr_fid INT;
DECLARE @comapared_ogr_fid INT;
DECLARE @last_created_set_id INT=0;
WHILE 1=1
BEGIN
FETCH NEXT FROM c_id INTO @ogr_fid,@comapared_ogr_fid;
IF @@FETCH_STATUS<>0 BREAK;
DECLARE @set_id_1 INT=(SELECT set_id FROM #sets WHERE fid=@ogr_fid);
DECLARE @set_id_2 INT=(SELECT set_id FROM #sets WHERE fid=@comapared_ogr_fid);
IF @set_id_1 IS NOT NULL AND @set_id_2 IS NOT NULL
CONTINUE;
ELSE IF @set_id_1 IS NOT NULL
INSERT INTO #sets(set_id,fid)VALUES(@set_id_1,@comapared_ogr_fid);
ELSE IF @set_id_2 IS NOT NULL
INSERT INTO #sets(set_id,fid)VALUES(@set_id_2,@ogr_fid);
ELSE
BEGIN
DECLARE @id_min INT=CASE WHEN @ogr_fid<@comapared_ogr_fid THEN @ogr_fid ELSE @comapared_ogr_fid END;
DECLARE @id_check INT;
WHILE 1=1
BEGIN
SET @id_check=(
SELECT MIN(identifier)
FROM (
SELECT MIN(ogr_fid) FROM #id WHERE comapared_ogr_fid=@id_min AND ogr_fid<@id_min HAVING MIN(ogr_fid) IS NOT NULL
UNION ALL
SELECT MIN(comapared_ogr_fid) FROM #id WHERE ogr_fid=@id_min AND comapared_ogr_fid<@id_min HAVING MIN(comapared_ogr_fid) IS NOT NULL
) AS lu(identifier)
);
IF @id_check IS NULL
BREAK;
SET @id_min=@id_check;
END
DECLARE @set_id_min INT=(SELECT set_id FROM #sets WHERE fid=@id_min);
IF @set_id_min IS NULL
BEGIN
SET @last_created_set_id=@last_created_set_id+1;
SET @set_id_min=@last_created_set_id;
INSERT INTO #sets(set_id,fid)VALUES(@set_id_min,@id_min);
END
IF @ogr_fid<>@id_min
INSERT INTO #sets(set_id,fid)VALUES(@set_id_min,@ogr_fid);
IF @comapared_ogr_fid NOT IN (@ogr_fid,@id_min)
INSERT INTO #sets(set_id,fid)VALUES(@set_id_min,@comapared_ogr_fid);
END
END
CLOSE c_id;
DEALLOCATE c_id;
SELECT
id.ogr_fid,
id.comapared_ogr_fid,
s.set_id AS Gr_ID
FROM
#id AS id
INNER JOIN #sets AS s ON
s.fid=id.ogr_fid
ORDER BY
s.set_id,
id.ID;
DROP TABLE #sets;
DROP TABLE #id;
结果:
+---------+-------------------+-------+
| ogr_fid | comapared_ogr_fid | SP_ID |
+---------+-------------------+-------+
| 8 | 10 | 1 |
| 6 | 8 | 1 |
| 10 | 4 | 1 |
| 5 | 3 | 2 |
| 5 | 2 | 2 |
| 12 | 15 | 3 |
+---------+-------------------+-------+