sqlite3 JOIN,GROUP_CONCAT使用distinct与自定义分隔符

时间:2012-11-14 16:24:57

标签: sql sqlite group-concat

给定一个“事件”表,其中每个事件可能与零个或多个“发言者”以及零个或多个“术语”相关联,那些通过联接表与事件相关联的记录,我需要生成一个包含所有事件的表每行有一列,表示与每个事件相关的“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

5 个答案:

答案 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),',',';')