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

aiw*_*ams 12 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
Run Code Online (Sandbox Code Playgroud)

group_concat聚合函数可以使用'distinct'来删除重复,但遗憾的是它不支持自定义分隔符,我真的需要它.我留下了这些结果:

1|Soccer|Bobby|Ball
2|Baseball|Bobby|Ball,Bat,Helmets
3|Football|Bobby,Jane|Ball,Helmets
Run Code Online (Sandbox Code Playgroud)

我的问题是:有没有办法可以形成查询或更改数据结构以获得我想要的结果?

请记住,这是我需要的sqlite3查询,我无法添加自定义C聚合函数,因为这是针对Android部署的.

我创建了一个要点,让您可以轻松地测试可能的解决方案:https://gist.github.com/4072840

CL.*_*CL. 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
Run Code Online (Sandbox Code Playgroud)


mur*_*urb 6

我也遇到了这个问题,但想出了一个我发现更容易理解的方法。由于 SQLite 报告SQLite3::SQLException: DISTINCT aggregates must have exactly one argument,问题似乎与GROUP_CONCAT方法没有太大关系,而是与使用DISTINCTGROUP_CONCAT...

当您将 DISTINCT 'subquery' 封装在一个REPLACE实际上什么都不做的方法中时,您可以获得 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;
Run Code Online (Sandbox Code Playgroud)

但实际上我会认为这是一个 SQLite 错误/不一致,或者我错过了什么?


naw*_*fal 5

奇怪的是,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;
Run Code Online (Sandbox Code Playgroud)

  • 这是我自己使用的解决方案,所以我不会投反对票。避免替换合法逗号可能失败的答案当然是公认的答案:) 谢谢您的时间。 (3认同)