从带数字的数组字符串到数组字符串文本的查询结果?

Query result from array string with numbers to array string text?

我有两个 SQL 服务器 table。

第一个table:Product

Id Title Tags
1 P1583 2,5
2 P1234 1,3
3 P1456 1

第二个 table - Tag:

Id Title
1 Pants
2 Shorts
3 Shirts
4 Tshirts
5 Skirts

我想要这个结果

ProductId Title TagName
1 P1583 Short,Skirts
2 P1234 Pants,Shirts
3 P1456 Pants

如何编写查询?

SELECT
    P.Id AS ProductId,
    P.Title AS Title,
    ????
FROM 
    Product P
LEFT JOIN 
    Tag T ON T.Id = P.Tags  --- (this is not working)

你的table

declare @r TABLE (
   Id    int  NOT NULL 
  ,Title VARCHAR(10) NOT NULL
  ,Tags  VARCHAR(30) NOT NULL
);
INSERT INTO @r(Id,Title,Tags) VALUES (1,'P1583','2,5');
INSERT INTO @r(Id,Title,Tags) VALUES (2,'P1234','1,3');
INSERT INTO @r(Id,Title,Tags) VALUES (3,'P1456','1');

declare @t TABLE (
   Id    int  NOT NULL PRIMARY KEY 
  ,Title VARCHAR(70) NOT NULL
);
INSERT INTO @t(Id,Title) VALUES (1,'Pants');
INSERT INTO @t(Id,Title) VALUES (2,'Shorts');
INSERT INTO @t(Id,Title) VALUES (3,'Shirts');
INSERT INTO @t(Id,Title) VALUES (4,'Tshirts');
INSERT INTO @t(Id,Title) VALUES (5,'Skirts');

生成结果的查询应该拆分标签并再次与第二个 table

的标题合并
with t as(
SELECT Id,Title,
    PARSENAME(REPLACE(Tags,',','.'),2) 'Tag1' ,
    PARSENAME(REPLACE(Tags,',','.'),1) 'Tag2'
FROM @r)
select t.id,t.Title,concat(t1.Title,iif(t1.Title is null,'',','),t2.Title) 
tagName from t
full join @t t1 on t1.id=t.Tag1
join @t t2 on t2.id=t.Tag2

因此,创建数据:

CREATE TABLE #t (id int, title nvarchar(5), tags nvarchar(3));

INSERT INTO #t (id,title,tags)
VALUES
(1,'P1583','2,5'),
(2,'P1234','1,3'),
(3,'P1456','1');

CREATE TABLE #tag (id int, title nvarchar(10));

INSERT INTO #tag (id,title)
VALUES
(1,'Pants'),
(2,'Shorts'),
(3,'Shirts'),
(4,'Tshirts'),
(5,'Skirts');

并且使用 STRING_SPLIT 和 CROSS APPLY 给我们:

SELECT #t.id, #t.title, #t.tags, tags.value, #tag.title
FROM #t
CROSS APPLY STRING_SPLIT(#t.tags,',') tags
INNER JOIN #tag ON tags.value = #tag.id;
id title tags value title
1 P1583 2,5 2 Shorts
1 P1583 2,5 5 Skirts
2 P1234 1,3 1 Pants
2 P1234 1,3 3 Shirts
3 P1456 1 1 Pants

从那里你们 STRING_AGG 回到了一起:

WITH exp
AS (
SELECT #t.id, #t.title, #t.tags, tags.value, #tag.title AS tag_title
FROM #t
CROSS APPLY STRING_SPLIT(#t.tags,',') tags
INNER JOIN #tag ON tags.value = #tag.id
)
SELECT id, title, STRING_AGG(tag_title,',') WITHIN GROUP (ORDER BY tag_title) AS tag_titles
FROM exp
GROUP BY id, title;

进行拆分和 re-aggregate 的另一种方法是修改@FlexYourData 的出色答案:

SELECT
  p.Id,
  p.Title,
  tags.TagName
FROM Product p
CROSS APPLY (
    SELECT
        TagName = STRING_AGG(t.Title, ',')
    FROM STRING_SPLIT(p.Tags, ',') tags
    INNER JOIN Tag t ON tags.value = t.id
) tags;

理想情况下,您应该规范化架构并创建单独的联接 table:

CREATE TABLE ProductTag (
    ProductId REFERENCES Product (Id),
    TagId REFERENCES Tag (Id)
);
INSERT ProductTag (ProductId, TagId)
SELECT
  p.Id,
  tags.value
FROM Product p
CROSS APPLY STRING_SPLIT(p.Tags, ',') tags;

那么您的查询变为:

SELECT
  p.Id,
  p.Title,
  tags.TagName
FROM Product p
CROSS APPLY (
    SELECT
        TagName = STRING_AGG(t.Title, ',')
    FROM ProductTags pt
    INNER JOIN Tag t ON pt.TagId = t.id
    WHERE pt.ProductId = p.Id
) tags;