给定一个“事件”表,其中每个事件可能与零个或多个“发言者”以及零个或多个“术语”相关联,那些通过联接表与事件相关联的记录,我需要生成一个包含所有事件的表每行有一列,表示与每个事件相关的“speaker_names”和“term_names”列表。
但是,当我运行查询时,我在speaker_names和term_names值中有重复,因为连接表为每个发言者和事件的术语每个关联产生一行:
1|Soccer|Bobby|Ball
2|Baseball|Bobby - Bobby - Bobby|Ball - Bat - Helmets
3|Football|Bobby - Jane - Bobby - Jane|Ball - Ball - Helmets - Helmets
group_concat聚合函数可以使用'distinct'来删除重复,但遗憾的是它并不支持我自己需要的自定义分隔符。我留下了这些结果:
1|Soccer|Bobby|Ball
2|Baseball|Bobby|Ball,Bat,Helmets
3|Football|Bobby,Jane|Ball,Helmets
我的问题是:有没有办法可以形成查询或更改数据结构以获得我想要的结果?
请记住,这是我需要的sqlite3查询,我无法添加自定义C聚合函数,因为这是针对Android部署的。
我创建了一个要点,让您可以轻松测试可能的解决方案:https://gist.github.com/4072840
答案 0 :(得分:8)
相互独立地查找发言人/任期名称:
SELECT _id,
name,
(SELECT GROUP_CONCAT(name, ';')
FROM events_speakers
JOIN speakers
ON events_speakers.speaker_id = speakers._id
WHERE events_speakers.event_id = events._id
) AS speaker_names,
(SELECT GROUP_CONCAT(name, ';')
FROM events_terms
JOIN terms
ON events_terms.term_id = terms._id
WHERE events_terms.event_id = events._id
) AS term_names
FROM events
答案 1 :(得分:4)
我也遇到了这个问题,但我想出了一个方法,我发现它更容易理解。由于SQLite报告SQLite3::SQLException: DISTINCT aggregates must have exactly one argument
,问题似乎与GROUP_CONCAT
方法无关,而是在DISTINCT
内使用GROUP_CONCAT
...
当你在一个REPLACE
方法中封装DISTINCT'子查询'时实际什么都不做你可以有相对简单的nawfal的建议而没有只能连接逗号的缺点少了正确的字符串。
SELECT events._id, events.name,
(group_concat(replace(distinct speakers.name),'',''), ' - ') AS speaker_names,
(group_concat(replace(distinct speakers.name),'',''), ' - ') AS term_names
FROM events
LEFT JOIN
(SELECT et.event_id, ts.name
FROM terms ts
JOIN events_terms et ON ts._id = et.term_id
) terms ON events._id = terms.event_id
LEFT JOIN
(SELECT sp._id, es.event_id, sp.name
FROM speakers sp
JOIN events_speakers es ON sp._id = es.speaker_id
) speakers ON events._id = speakers.event_id
GROUP BY events._id;
但实际上我会认为这是一个SQLite错误/不一致,或者我错过了什么?
答案 2 :(得分:3)
奇怪的是,SQLite不支持!
您可以使用Replace(X, Y, Z)
。但您必须确保列中没有有效的,
值。
SELECT events._id, events.name,
REPLACE(group_concat(distinct speakers.name), ',', ' - ') AS speaker_names,
REPLACE(group_concat(distinct terms.name), ',', ' - ') AS term_names
FROM events
LEFT JOIN
(SELECT et.event_id, ts.name
FROM terms ts
JOIN events_terms et ON ts._id = et.term_id
) terms ON events._id = terms.event_id
LEFT JOIN
(SELECT sp._id, es.event_id, sp.name
FROM speakers sp
JOIN events_speakers es ON sp._id = es.speaker_id
) speakers ON events._id = speakers.event_id
GROUP BY events._id;
答案 3 :(得分:0)
只需设置一个正确的解决方法(murb的答案是扼杀括号)。
<强>问题:强>
group_concat(distinct column_name, 'custom_separator')
将custom_separator
作为distinct
的一部分。
<强>溶液强>
我们需要一些无操作让SQLite知道distinct
已完成(包装distcint及其参数)。
No-op可以替换为空字符串作为第二个参数(documentation to replace)。
group_concat(replace(distinct column_name, '', ''), 'custom_separator')
修改强>
刚刚发现它不起作用:-( - 可以被调用,但distinct
不再起作用
答案 4 :(得分:0)
问题出现在group_concat(X,Y)表达式,而不是group_concat(X)表达式。
group_concat(distinct X)效果很好。
所以,如果','对你有好处,没有问题,但如果你想要一个';'而不是','(并且你确定没有','在原文中),你可以这样做:
replace(group_concat(distinct X),',',';')