在this fiddle中,我有一个名为“tags”的表。它有四列:
id counter sessionid tag
(1, 1, 'session1', 'start'),
(2, 2, 'session1', 'sessionname1'),
(3, 3, 'session1', 'unimportant tag'),
(4, 4, 'session1', 'unimportant tag'),
(5, 5, 'session1', 'end'),
(6, 1, 'session2', 'start'),
(7, 2, 'session2', 'sessionname2'),
(8, 3, 'session2', 'end')
我想显示此表的所有列 PLUS 一个名为“name”的附加行。 此列中的数据由以下条件生成:
该名称写在每个 sessionid的第二行。这实际上意味着我检查哪一行标记为“开始”。然后,会话名称将写入列标记,其中计数器高1 ,而不是带有tag =“start”的行。
我尝试了第一个查询,它适用于第一个 sessionid ,但后来在第二个sessionid失败,因为它在每一行写入“sessionname1”。对于ID为6,7,8的行,正确的查询将返回name =“sessionname2”。
SELECT t1.*,
(SELECT top 1 t2.tag
FROM tags t2
JOIN ( SELECT * FROM tags WHERE tag = 'start' ) t3
ON (t2.counter = t3.counter + 1) AND t3.sessionid = t2.sessionid
) AS name
FROM tags t1
为了在每一行中获得正确的名称,我需要更改什么?
结帐我的SQL Fiddle
当然预期输出显示所有行。 它看起来如下:
id counter sessionid tag name
(1, 1, 'session1', 'start', 'sessionname1'),
(2, 2, 'session1', 'sessionname1', 'sessionname1'),
(3, 3, 'session1', 'unimportant tag','sessionname1'),
(4, 4, 'session1', 'unimportant tag','sessionname1'),
(5, 5, 'session1', 'end', 'sessionname1'),
(6, 1, 'session2', 'start', 'sessionname2'),
(7, 2, 'session2', 'sessionname2', 'sessionname2'),
(8, 3, 'session2', 'end', 'sessionname2')
重要提示:
跟踪计数器列比具有“start”的行强1 更重要。每次2 NOT ,“start”行也有可能跟踪计数器= 80,然后跟踪计数器必须为81.
答案 0 :(得分:1)
以下内容适用于您:
SELECT tags.*, tagnames.tag AS sessionname
FROM tags
INNER JOIN
(SELECT sessionid, tag
FROM tags WHERE counter = 2) AS tagnames
ON tags.sessionid = tagnames.sessionid
此方法的工作原理是创建一个只包含会话标识符和名称(这是INNER JOIN子查询)的表,然后我们将其连接回主集,以允许我们将会话名称作为一个独特的引入列。
它有两个假设:
INNER JOIN
指定我们始终希望会话名称counter = 2
修改强>
从您的评论中,我发现我们无法通过counter = 2
来识别名称行,但它始终是给定sessionid的second
行。因此,我们可以执行以下操作来挑选每个sessionid的第二行:
SELECT @previous_session := null;
SELECT
sessionid,
counter,
tag,
@counter_rank := IF(@previous_session = sessionid, @counter_rank + 1, 1) AS counter_rank,
@previous_session := sessionid
FROM tags
ORDER BY sessionid, counter ASC
这会使用每个会话组user defined variable生成一个“人工”行号,这样我们就可以找到按sessionid和counter排序的第二条记录。
将其纳入第一个查询会给我们:
SELECT @previous_session := null;
SELECT tags.*, tagnames.tag AS sessionname
FROM tags
INNER JOIN
(SELECT countranks.sessionid, countranks.tag
FROM (
SELECT
sessionid,
counter,
tag,
@counter_rank := IF(@previous_session = sessionid, @counter_rank + 1, 1) AS counter_rank,
@previous_session := sessionid
FROM tags
ORDER BY sessionid, counter ASC
) AS countranks WHERE countranks.counter_rank = 2
) AS tagnames
ON tags.sessionid = tagnames.sessionid;
答案 1 :(得分:0)
您可以尝试:
SELECT tags.id, tags.counter, tags.sessionid, tags.tag, t.name
FROM (tags
LEFT JOIN
(SELECT sessionid, tag as name
FROM tags
WHERE counter = 2) as t
ON tags.sessionid = t.sessionid
) ;
上看起来经过精心测试
答案 2 :(得分:0)
试试这个:
select b.*, (select tag from tags a where a.counter = 2 and a.sessionid = b.sessionid) 'NAME'
from tags b