MySQL:如何用GROUP BYselect每组的第N个值
MySQL: how to select the Nth value of each group with GROUP BY
我想 select 每个 new_threads 组的第二个响应列值,如果它是一组 1 行,则值为零。
new_treads|response
------------------
1 | 0
1 | 1
2 | 0
2 | 0
2 | 1
... | ...
9 | 0
9 | 1
9 | 0
10 | 0
输出为:
new_treads|response
------------------
1 | 1
2 | 0
... | ...
9 | 1
10 | 0
到目前为止,我了解如何使用 MIN 获得第一个,但我需要第二个
SELECT
thread,
min(response)
FROM messages
GROUP BY thread;
我想使用 GROUP BY,因为我也在为其他 SELECT 使用 GROUP BY
谢谢!
由于行不是 "numbered",您需要为每个组创建一个编号,然后 select。我会用用户变量来做到这一点:
select thread, response
from (
select @n := (case
when m.thread = @prev_thread then @n
else 0
end) + 1 as n -- If the current thread is the same as the
-- previous row, then increase the counter,
-- else, reset it
, @prev_thread := m.thread as thread -- Update the value of
-- @prev_thread
, m.response
from
(select @n := 0, @prev_thread := 0) as init
-- The 'init' subquery initializes the
-- temp variables:
-- @n is a counter
-- @prev_thread is an identifier for the
-- previous thread id
, messages as m
order by m.thread -- You need to add a second column to order
-- each response (such as "response_id", or
-- something like that), otherwise the returned
-- row may be a random one
) as a
where n = 2; -- Select the rows from the subquery where the counter equals 2
上面的方法可以很好地找到每组的第二行,但前提是有一个。那么现在:如果没有第二行,如何获得 NULL
值?
最简单的方法是使用左连接:
select t.thread, b.response
from (select distinct thread from messages) as t
left join (
-- Put the above query here
) as b on t.thread = b.thread;
SELECT
thread,
min(response)
FROM messages
GROUP BY thread
HAVING response > min(response)
试试这个只是想知道它是否有效
我想详细说明上面的答案。虽然它对我来说效果很好,但我花了一些时间来拼凑上下文并概括它,以便我可以将它应用到我的代码中。我希望这个答案能更好地概括上面列出的内容...
SELECT *
FROM (SELECT distinct keyField --- keyField is the field the query is grouping by
FROM TABLE
-- Add keyField Constraint --
-- Add non-keyField Constraint --
INNER JOIN (SELECT *,
@n:=(CASE -- Iterating through...
WHEN keyField = @prev_keyField -- When keyField value == previous keyField value
THEN @n:=@n+1 -- Define n as the row in the group
ELSE 1 -- When keyField value != previous keyField value, then n is the 1st row in the group
END) as n,
@prev_keyField:= keyField -- Define previous keyField value for the next iteration
FROM (SELECT @n:=0,@prev_keyField:=0) r,TABLE as p
-- Add non-keyField Constraint--
ORDER BY keyField,sortField DESC -- Order by keyField and the field you are sorting by
-- ei. keyField could be `thread`,
-- and sort field could be `timestamp` if you are sorting by time
) s ON s.keyField = p.keyField
WHERE s.n = 2 -- Define which row in the group you want in the query
我想 select 每个 new_threads 组的第二个响应列值,如果它是一组 1 行,则值为零。
new_treads|response
------------------
1 | 0
1 | 1
2 | 0
2 | 0
2 | 1
... | ...
9 | 0
9 | 1
9 | 0
10 | 0
输出为:
new_treads|response
------------------
1 | 1
2 | 0
... | ...
9 | 1
10 | 0
到目前为止,我了解如何使用 MIN 获得第一个,但我需要第二个
SELECT
thread,
min(response)
FROM messages
GROUP BY thread;
我想使用 GROUP BY,因为我也在为其他 SELECT 使用 GROUP BY
谢谢!
由于行不是 "numbered",您需要为每个组创建一个编号,然后 select。我会用用户变量来做到这一点:
select thread, response
from (
select @n := (case
when m.thread = @prev_thread then @n
else 0
end) + 1 as n -- If the current thread is the same as the
-- previous row, then increase the counter,
-- else, reset it
, @prev_thread := m.thread as thread -- Update the value of
-- @prev_thread
, m.response
from
(select @n := 0, @prev_thread := 0) as init
-- The 'init' subquery initializes the
-- temp variables:
-- @n is a counter
-- @prev_thread is an identifier for the
-- previous thread id
, messages as m
order by m.thread -- You need to add a second column to order
-- each response (such as "response_id", or
-- something like that), otherwise the returned
-- row may be a random one
) as a
where n = 2; -- Select the rows from the subquery where the counter equals 2
上面的方法可以很好地找到每组的第二行,但前提是有一个。那么现在:如果没有第二行,如何获得 NULL
值?
最简单的方法是使用左连接:
select t.thread, b.response
from (select distinct thread from messages) as t
left join (
-- Put the above query here
) as b on t.thread = b.thread;
SELECT
thread,
min(response)
FROM messages
GROUP BY thread
HAVING response > min(response)
试试这个只是想知道它是否有效
我想详细说明上面的答案。虽然它对我来说效果很好,但我花了一些时间来拼凑上下文并概括它,以便我可以将它应用到我的代码中。我希望这个答案能更好地概括上面列出的内容...
SELECT *
FROM (SELECT distinct keyField --- keyField is the field the query is grouping by
FROM TABLE
-- Add keyField Constraint --
-- Add non-keyField Constraint --
INNER JOIN (SELECT *,
@n:=(CASE -- Iterating through...
WHEN keyField = @prev_keyField -- When keyField value == previous keyField value
THEN @n:=@n+1 -- Define n as the row in the group
ELSE 1 -- When keyField value != previous keyField value, then n is the 1st row in the group
END) as n,
@prev_keyField:= keyField -- Define previous keyField value for the next iteration
FROM (SELECT @n:=0,@prev_keyField:=0) r,TABLE as p
-- Add non-keyField Constraint--
ORDER BY keyField,sortField DESC -- Order by keyField and the field you are sorting by
-- ei. keyField could be `thread`,
-- and sort field could be `timestamp` if you are sorting by time
) s ON s.keyField = p.keyField
WHERE s.n = 2 -- Define which row in the group you want in the query