如何关联不直接关联的列?

时间:2019-02-20 00:31:41

标签: sql sql-server

我有此数据:

label    ui     dc          mapId

1        209459 50580-590   1      
1        198440 50580-590   2      

2        209459 50580-449   3      
2        198440 50580-449   4      

3        198440 43353-066   5      
3        198440 43353-067   6      
3        198440 43353-059   7           

4        187878 89999-876   8 

使用label列与此查询一起在其中插入并映射它:

DECLARE @dc TABLE (label int, dc varchar(50))
DECLARE @ui TABLE (label int, ui varchar(50))

INSERT INTO @DC
VALUES (1, '50580-590'), (2, '50580-449'), (3, '43353-066'), (3, '43353-067'), (3, '43354-059'), (4, '89999-876')

INSERT INTO @UI
VALUES (1, '209459'), (1, '198440'), (2, '209459'), (2, '198440'), (3, '198440'), (4, '187878')

SELECT *
FROM @dc A
INNER JOIN (    
    SELECT *
    FROM @ui
    ) B
ON A.label = B.label

我正在尝试查找相互关联的行。例如,我要查找dc = 43353-059所在的行以及与该行关联的ui,而该ui就是mapId = 7所在的行。在该行ui = 198440中,所以在执行此操作之后,我想查找ui为198440的行,然后再查看标签。如果在mapId = 2所在的行,则198440的ui具有label of 1 but on mapId 1 ui of 209459的ui也与label of 1关联。这样,您可以说mapId 1 - 7是相关的。使用该逻辑,im尝试使用顶部的数据进行查询并获得以下结果:

label    ui     dc          masterId

1        209459 50580-590   1
1        198440 50580-590   2

3        209459 50580-449   3
3        198440 50580-449   4

3        198440 43353-066   5
3        198440 43353-067   6
3        198440 43353-059   7

4        187878 89999-876   1

由于我无法以任何方式将mapId 8与我从masterId列的1开始的其他行相关联。任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:1)

请看看

DECLARE @Crossings TABLE (Label INT,Value INT)
INSERT INTO @Crossings(label,[Value])
SELECT DISTINCT up.Label,up.Value
FROM (
    SELECT dc.label AS [Label],dc.RelatedLabel AS [1],ui.label AS [2],ui.RelatedLabel AS [3]
    FROM (
        SELECT dc.label,dc2.label AS [RelatedLabel]
        FROM @dc dc
        LEFT JOIN @dc dc2 ON dc2.dc = dc.dc
    ) dc
    INNER JOIN (
        SELECT ui.label,ui2.label AS [RelatedLabel]
        FROM @ui ui
        LEFT JOIN @ui ui2 On ui2.ui = ui.ui
    ) ui ON ui.label = dc.label OR ui.label = dc.RelatedLabel OR ui.RelatedLabel = dc.RelatedLabel
) a
UNPIVOT(Value FOR Param IN ([1],[2],[3])) up
ORDER BY up.label
;

DECLARE @Group TABLE (Label INT,TheGroup NVARCHAR(255))
;WITH cte AS (
    SELECT DISTINCT g.label,g2.label AS [RelatedLabel]
    FROM @Crossings g
    LEFT JOIN @Crossings g2 ON (g2.[Value] = g.[label] OR g2.[label] = g.[Value])
)
INSERT INTO @Group(Label,TheGroup)
SELECT DISTINCT d.Label
    ,STUFF((SELECT DISTINCT ',' + CONVERT(NVARCHAR(50),r.RelatedLabel) FROM cte r WHERE r.Label = d.Label ORDER BY 1 FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)'),1,1,'') AS [TheGroup]
FROM cte d
;


SELECT dc.label,dc.dc,ui.ui
    ,ROW_NUMBER()OVER(ORDER BY (SELECT 1)) AS [MapId]
    ,ROW_NUMBER()OVER(PARTITION BY g.TheGroup ORDER BY dc.label) AS [MasterId]
FROM @dc dc
INNER JOIN @ui ui ON ui.label = dc.label
INNER JOIN @Group g ON g.Label = dc.label
;

答案 1 :(得分:1)

使用Vitaly的答案使它正常工作,但是再应用两次Unpivot来查找所有相关标签,然后像他一样浓缩它们:

DECLARE @dc TABLE (label int, dc varchar(50))
DECLARE @ui TABLE (label int, ui varchar(50))
DECLARE @RelatedLabel TABLE (Label int, [group] int)
DECLARE @Crossings TABLE (Label INT,Value INT)
DECLARE @Crossings2 TABLE (Label INT, Value INT)
DECLARE @RelatedLabel2 TABLE (Label int, Value int)
DECLARE @Result TABLE (Label INT, dc varchar(50), ui varchar(50), seqnum int, masterId int)

INSERT INTO @DC
VALUES (1, '50580-590'), (2, '50580-449'), (3, '43353-066'), (3, '43353-067'), (3, '43354-059'), (4, '89999-876')
, (5, '88888-90')

INSERT INTO @UI
VALUES (1, '209459'), (1, '198440'), (2, '209459'), (2, '198440'), (3, '198440'), (4, '187878')
, (5, '187878'), (5, '209459')

INSERT INTO @Crossings(label,[Value])
SELECT DISTINCT up.Label,up.Value
FROM (
    SELECT dc.label AS [Label],dc.RelatedLabel AS [1],ui.label AS [2],ui.RelatedLabel AS [3]
    FROM (
        SELECT dc.label,dc2.label AS [RelatedLabel]
        FROM @dc dc
        LEFT JOIN @dc dc2 ON dc2.dc = dc.dc
    ) dc
    INNER JOIN (
        SELECT ui.label,ui2.label AS [RelatedLabel]
        FROM @ui ui
        LEFT JOIN @ui ui2 On ui2.ui = ui.ui
    ) ui ON ui.label = dc.label OR ui.label = dc.RelatedLabel OR ui.RelatedLabel = dc.RelatedLabel OR ui.RelatedLabel = dc.label
) a
UNPIVOT(Value FOR Param IN ([1],[2],[3])) up
ORDER BY up.label
;

INSERT INTO @RelatedLabel
SELECT DISTINCT g.label,g2.label AS [RelatedLabel]
    FROM @Crossings g
    LEFT JOIN @Crossings g2 ON (g2.[Value] = g.[label] OR g2.[label] = g.[Value])

INSERT INTO @RelatedLabel2
SELECT distinct A.Label as Label, B.label AS [1]
FROM @RelatedLabel A
LEFT JOIN (
    SELECT *
    FROM @RelatedLabel
    ) B
ON A.[group] = b.[group] OR A.label = B.[group]

INSERT INTO @Crossings2
SELECT distinct A.Label as Label, B.label AS [1]
FROM @RelatedLabel2 A
LEFT JOIN (
    SELECT *
    FROM @RelatedLabel2
    ) B
ON A.value = b.value OR A.label = B.value

DECLARE @Group TABLE (Label INT,TheGroup VARCHAR(255))
;WITH cte AS (
    SELECT DISTINCT g.label,g2.label AS [RelatedLabel]
    FROM @Crossings2 g
    LEFT JOIN @Crossings2 g2 ON (g2.[Value] = g.[label] OR g2.[label] = g.[Value])
)
INSERT INTO @Group(Label,TheGroup)
SELECT DISTINCT d.Label
    ,STUFF((SELECT DISTINCT ',' + CONVERT(NVARCHAR(50),r.RelatedLabel) FROM cte r WHERE r.Label = d.Label ORDER BY 1 FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)'),1,1,'') AS [TheGroup]
FROM cte d
;


SELECT dc.label,dc.dc,ui.ui
    ,ROW_NUMBER() OVER(PARTITION BY g.TheGroup ORDER BY dc.label) AS seqnum
FROM @dc dc
INNER JOIN @ui ui ON ui.label = dc.label
INNER JOIN @Group g ON g.Label = dc.label
;

答案 2 :(得分:-1)

ROW_NUMBER模数7?

DECLARE @dc TABLE (label int, dc varchar(50))
DECLARE @ui TABLE (label int, ui varchar(50))

INSERT INTO @DC
VALUES (1, '50580-590'), (2, '50580-449'), (3, '43353-066'), (3, '43353-067'), (3, '43354-059'), (4, '89999-876')

INSERT INTO @UI
VALUES (1, '209459'), (1, '198440'), (2, '209459'), (2, '198440'), (3, '198440'), (4, '187878')

SELECT 
  A.label
  , B.ui
  , A.dc
  , ROW_NUMBER() OVER(ORDER BY a.label, b.ui DESC, a.dc DESC) AS mapId
  , CASE 
      WHEN ROW_NUMBER() OVER(ORDER BY a.label, b.ui DESC, a.dc DESC) % 7 = 0 THEN 7 
      ELSE ROW_NUMBER() OVER(ORDER BY a.label, b.ui DESC, a.dc DESC) % 7 
    END masterId
FROM @dc A
INNER JOIN (    
    SELECT *
    FROM @ui
    ) B
ON A.label = B.label

ROW_NUMBER (Transact-SQL)
% (Modulus) (Transact-SQL)