在进行多重连接时,我不想连接组中的所有字符串。以下是我的方案
表格 - 日志
id | appname | level
---------------------
1 | app1 | debug
2 | app3 | warn
3 | app1 | debug
4 | app2 | info
表格 - log_tag
id | text
----------
1 | tag_wink
2 | tag_steve
3 | ignore
4 | jimmy
表格 - log_tag_map
tag_id | log_id
---------------
1 | 1
1 | 2
2 | 4
2 | 1
3 | 1
我的目标是;对于每个日志,请加入用逗号分隔的所有标记。
这是我想要的输出
id | appname | level | text
----------------------------
1 | app1 | debug | tag_wink, tag_steve, ignore
2 | app3 | warn | tag_wink
3 | app1 | debug |
4 | app2 | info | tag_steve
我已经尝试了许多事情,但似乎无法获得所需的输出。
这为每个日志提供了一个tag_text
SELECT
log_table.id,
log_table.appname,
log_table.level,
log_tag_table.text,
FROM log_table
INNER JOIN [log_tag_map] log_tag_map_table
ON log_tag_map_table.log_id = log_table.id
INNER JOIN [log_tag] log_tag_table
ON log_tag_map_table.tag_id = log_tag_table.id
ORDER BY log_table.id
在研究了T-SQL中的串联字符串后,我使用了着名的 FOR XML PATH 解决方案,但我似乎无法得到我想要的结果。我一直收到错误,说" log_tag_map_table.tag_id "是无效的,因为它不在聚合函数中。
SELECT
log_table.id,
MAX(log_table.appname),
MAX(log_table.level),
STUFF((
SELECT ', ' + [log_tag].text
FROM [log_tag]
WHERE
log_tag_map_table.tag_id = log_tag.id AND
log_tag_map_table.log_id = log_table.id
FOR XML PATH (''))
, 1
, 2
, '')
FROM log_table
INNER JOIN [log_tag_map] log_tag_map_table
ON log_tag_map_table.log_id = log_table.id
INNER JOIN [log_tag] log_tag_table
ON log_tag_map_table.tag_id = log_tag_table.id
GROUP BY log_table.id
ORDER BY log_table.id
答案 0 :(得分:2)
您可以通过在Group By
中添加重命名列来解决此问题。查询中的Group by
只是为了删除重复项。
我更喜欢APPLY
运算符而不是correlated-sub-query
。它看起来很简单,删除前导或尾随 comma
非常容易
SELECT DISTINCT log_table.id,
log_table.appname,
log_table.level,
LEFT(concat_text, Len(concat_text) - 1) as Concat_text
FROM log_table
OUTER apply (SELECT [log_tag].text + ','
FROM [log_tag_map] log_tag_map_table
JOIN log_tag
ON log_tag_map_table.tag_id = log_tag.id
WHERE log_tag_map_table.log_id = log_table.id
FOR XML PATH ('')) oa (concat_text)
ORDER BY log_table.id
演示:
架构设置
CREATE TABLE log_table
(
[id] INT,
[appname] VARCHAR(4),
[level] VARCHAR(5)
);
CREATE TABLE log_tag
(
[id] INT,
[text] VARCHAR(9)
);
CREATE TABLE log_tag_map
(
[tag_id] INT,
[log_id] INT
);
示例数据
INSERT INTO log_table
([id],[appname],[level])
VALUES (1,'app1','debug'),
(2,'app3','warn'),
(3,'app1','debug'),
(4,'app2','info');
INSERT INTO log_tag
([id],[text])
VALUES (1,'tag_wink'),
(2,'tag_steve'),
(3,'ignore'),
(4,'jimmy');
INSERT INTO log_tag_map
([tag_id],[log_id])
VALUES (1,1),
(1,2),
(2,4),
(2,1),
(3,1);
查询:
SELECT DISTINCT log_table.id,
log_table.appname,
log_table.level,
LEFT(concat_text, Len(concat_text) - 1) as Concat_Text
FROM log_table
OUTER apply (SELECT [log_tag].text + ','
FROM [log_tag_map] log_tag_map_table
JOIN log_tag
ON log_tag_map_table.tag_id = log_tag.id
WHERE log_tag_map_table.log_id = log_table.id
FOR XML PATH ('')) oa (concat_text)
Order by log_table.id
Reuslt:
╔════╦═════════╦═══════╦═══════════════════════════╗
║ id ║ appname ║ level ║ Concat_Text ║
╠════╬═════════╬═══════╬═══════════════════════════╣
║ 1 ║ app1 ║ debug ║ tag_wink,tag_steve,ignore ║
║ 2 ║ app3 ║ warn ║ tag_wink ║
║ 3 ║ app1 ║ debug ║ NULL ║
║ 4 ║ app2 ║ info ║ tag_steve ║
╚════╩═════════╩═══════╩═══════════════════════════╝
答案 1 :(得分:0)
这是使用CROSS APPLY
的方式。
SELECT Id ,appname,level,[text]
FROM (
SELECT log_table.id,
log_table.appname,
log_table.level
FROM log_table
) a
CROSS APPLY
(
SELECT CASE ROW_NUMBER() OVER(ORDER BY [log_tag].text) WHEN 1 THEN '' ELSE ', ' END +[log_tag].text [text()]
FROM [log_tag_map] log_tag_map_table
JOIN log_tag
ON log_tag_map_table.tag_id = log_tag.id
WHERE log_tag_map_table.log_id = a.id
ORDER BY
[log_tag].text
FOR XML PATH ('')
) b([text])
输出:
您还可以使用request.post('http://service.com/upload').form({key:'value'})
获取OP。
{{1}}
输出: