从 table 获取以逗号分隔的一组值,其中另一个 table 的另一个参考值出现两次(或更多)

Get comma-separated set of values from table where another reference value on another table appears twice (or more)

假设 SQL Server 2014 中的数据库设置如下:

DECLARE @MATERIAL TABLE (ID int, CODE varchar(30));

INSERT @MATERIAL (ID, CODE) VALUES
(1, 'D3033MBBY'),
(2, 'D3033MBTY'),
(3, '011130-01'),
(4, '011130-04C'),
(5, '021002'),
(6, '021017-B'),
(7, '021134-01'),
(8, '021135-01'),
(9, '021955-01'),
(10, '3LS91101-550'),
(11, 'D3049MBRB'),
(12, 'EF0118'),
(13, 'FV8130'),
(14, 'FY7009'),
(15, 'H05802'),
(16, 'D3033MRTE');

DECLARE @SUBSTITUTE TABLE (ID int, ITEID int, SUBSTITUTECODE varchar(100));

INSERT @SUBSTITUTE (ID, ITEID, SUBSTITUTECODE) VALUES
(5232, 1, '191045762418'),
(5442, 2, '191045762418'),
(6435, 3, '5206432380030'),
(6573, 4, '5206432380030'),
(6582, 5, '5206432357131'),
(6683, 6, '5206432369486'),
(7332, 7, '5206432380610'),
(7482, 8, '5206432380818'),
(7721, 9, '5206432346029'),
(7831, 10, '5205172116350'),
(8034, 11, '191045480992'),
(8184, 12, '4061622759543'),
(8284, 13, '4062058577497'),
(8573, 14, '4064039588089'),
(9438, 15, '4064048672519'),
(9746, 16, '191045762418');

SELECT sub.SUBSTITUTECODE
FROM @SUBSTITUTE AS sub
INNER JOIN @MATERIAL AS prod ON prod.ID = sub.ITEID
GROUP BY sub.SUBSTITUTECODE
HAVING COUNT(sub.SUBSTITUTECODE) > 1;

我想创建一个将产生以下结果集的查询:

CODES SUBSTITUTECODE
D3033MBBY,D3033MBTY,D3033MRTE 191045762418
011130-01,011130-04C 5206432380030

换句话说,我想在 @MATERIAL 中获得一组以逗号分隔的 CODE,其中 [=41] 中的那些记录有重复的 SUBSTITUTECODE 引用=] @SUBSTITUTE

间接地,我可以通过以下查询找到与那些重复的 SUBSTITUTECODE 相对应的 CODE

SELECT prod.CODE, sub.SUBSTITUTECODE
FROM @SUBSTITUTE AS sub
INNER JOIN @MATERIAL AS prod ON prod.ID = sub.ITEID
WHERE sub.SUBSTITUTECODE IN (SELECT sub.SUBSTITUTECODE
    FROM @SUBSTITUTE AS sub
    INNER JOIN @MATERIAL AS prod ON prod.ID = sub.ITEID
    GROUP BY sub.SUBSTITUTECODE
    HAVING COUNT(sub.SUBSTITUTECODE) > 1)

可以找到上述案例的工作 fiddle here

请注意,此场景的完整案例在 SQL Server 2014 上运行。

TIA

由于您使用的是 SQL Server 2014,因此您无法使用 STRING_AGG()

这是使用FOR XML PATH

的解决方案
WITH CTE AS
(
    SELECT prod.CODE, sub.SUBSTITUTECODE, 
           c = COUNT(*) OVER (PARTITION BY sub.SUBSTITUTECODE)
    FROM   @SUBSTITUTE AS sub
           INNER JOIN @MATERIAL AS prod ON prod.ID = sub.ITEID
),
CTE2 AS
(
    SELECT *
    FROM   CTE
    WHERE  c > 1
)
SELECT STUFF((SELECT ',' + CODE 
              FROM CTE2 x 
              WHERE x.SUBSTITUTECODE = c.SUBSTITUTECODE 
              FOR XML PATH('')), 1, 1, ''),
       SUBSTITUTECODE
FROM   CTE2 c
GROUP BY SUBSTITUTECODE

开局不错 fiddle,谢谢!如果我们只是把你已有的东西放在 CTE 中,我们可以围绕它编写一个标准的字符串聚合:

;WITH subs AS 
(
  SELECT prod.CODE, sub.SUBSTITUTECODE
  FROM @SUBSTITUTE AS sub
  INNER JOIN @MATERIAL AS prod ON prod.ID = sub.ITEID
  WHERE sub.SUBSTITUTECODE IN (SELECT sub.SUBSTITUTECODE
    FROM @SUBSTITUTE AS sub
    INNER JOIN @MATERIAL AS prod ON prod.ID = sub.ITEID
    GROUP BY sub.SUBSTITUTECODE
    HAVING COUNT(sub.SUBSTITUTECODE) > 1)
)
SELECT CODES = STUFF((SELECT ',' + CODE 
  FROM subs AS s2 WHERE s2.SUBSTITUTECODE = subs.SUBSTITUTECODE
  FOR XML PATH(''), TYPE).value(N'./text()[1]', N'nvarchar(max)'),1,1,''),
    SUBSTITUTECODE FROM subs
  GROUP BY SUBSTITUTECODE;

但是我们可以稍微简化这段代码,最重要的是避免引用两个表两次,像这样:

;WITH subs AS
(
  SELECT s.ITEID, s.SUBSTITUTECODE, m.CODE, 
    c = COUNT(*) OVER (PARTITION BY s.SUBSTITUTECODE)
  FROM @SUBSTITUTE AS s
  INNER JOIN @MATERIAL AS m
  ON m.ID = s.ITEID
)
SELECT CODES = STUFF((SELECT ',' + CODE
  FROM subs AS s2 WHERE s2.SUBSTITUTECODE = subs.SUBSTITUTECODE
  FOR XML PATH(''), TYPE).value(N'./text()[1]', N'nvarchar(max)'),1,1,''),
    SUBSTITUTECODE
  FROM subs 
  WHERE c > 1 
  GROUP BY SUBSTITUTECODE;

请注意,在更现代的 SQL Server (2017+) 版本中,STRING_AGG() 使这更容易:

SELECT CODES = STRING_AGG(m.CODE, ','), s.SUBSTITUTECODE
  FROM @SUBSTITUTE AS s
  INNER JOIN @MATERIAL AS m
  ON m.ID = s.ITEID
  GROUP BY s.SUBSTITUTECODE
  HAVING COUNT(*) > 1;