如何选择帖子的最后编辑版本?

时间:2016-08-27 20:25:16

标签: mysql sql mysql-select-db

这是表结构:

+----+-----------------------------+-----------+
| id |       post_content          | edited_id |
+----+-----------------------------+-----------+
| 1  | content 1                   | NULL      |
| 2  | content 2                   | NULL      |
| 3  | content 1 (edited)          | 1         |
| 4  | content 3                   | NULL      |
| 5  | content 4                   | NULL      |
| 6  | content 4 (edited)          | 5         |
| 7  | content 1 (edited)          | 1         |
+----+-----------------------------+-----------+

现在我想选择每篇文章的最新编辑版本。所以这是预期的结果:

+----+-----------------------------+-----------+
| id |       post_content          | edited_id |
+----+-----------------------------+-----------+
| 7  | content 1 (edited)          | 1         |
| 2  | content 2                   | NULL      |
| 4  | content 3                   | NULL      |
| 6  | content 4 (edited)          | 5         |
+----+-----------------------------+-----------+

我该怎么做?

5 个答案:

答案 0 :(得分:3)

SQL Fiddle 了解其运作方式。

首先,我们从" (edited)"删除post_content字符串部分(如果需要),为group by删除一个列,然后根据我们的组计算最大id,最后再加入同一个表,用于检索特定id的值。

SELECT
  goo.id,
  qa.post_content,
  qa.edited_id
FROM (
  SELECT
    MAX(id) AS id,
    post_content
  FROM (
    SELECT
      id,
      CASE WHEN locate(' (edited)', post_content) <> 0
           THEN left(post_content, locate(' (edited)', post_content) - 1)
           ELSE post_content
           END AS post_content,
      edited_id
    FROM qa
    ) foo
  GROUP BY post_content
  ) goo
  INNER JOIN qa ON goo.id = qa.id

<强>输出

+----+-----------------------------+-----------+
| id |       post_content          | edited_id |
+----+-----------------------------+-----------+
| 7  | content 1 (edited)          | 1         |
| 2  | content 2                   | NULL      |
| 4  | content 3                   | NULL      |
| 6  | content 4 (edited)          | 5         |
+----+-----------------------------+-----------+

CASE解释

-- if post_content contains " (edited)" then locate() will return value of it's position
CASE WHEN locate(' (edited)', post_content) <> 0
  -- we're removing the " (edited)" part by doing left()-1 because we want the string to finish before first character of " (edited)"
     THEN left(post_content, locate(' (edited)', post_content) - 1)
  -- if post_content doesn't contain " (edited)" then simply return post_content
     ELSE post_content
     END AS post_content

答案 1 :(得分:3)

这应该有效:

select qa.*
from(
  select max(id) as max_post_id
  from qa
  group by coalesce(edited_id, id)
) maxids
join qa on qa.id = maxids.max_post_id

http://sqlfiddle.com/#!9/6018b2/1

如果您想按edited_id订购:

select qa.*
from(
  select max(id) as max_post_id, coalesce(edited_id, id) as edited_id
  from qa
  group by coalesce(edited_id, id)
) maxids
join qa on qa.id = maxids.max_post_id
order by maxids.edited_id

http://sqlfiddle.com/#!9/6018b2/9

答案 2 :(得分:3)

就像@PaulSpiegel在评论中所建议的那样,我认为桌面结构的一个小改动会让你的生活更轻松。
我建议您使用content_id更改+----+-----------------------------+------------+ | id | post_content | content_id | +----+-----------------------------+------------+ | 1 | content 1 | 1 | | 2 | content 2 | 2 | | 3 | content 1 (edited) | 1 | | 4 | content 3 | 3 | | 5 | content 4 | 4 | | 6 | content 4 (edited) | 4 | | 7 | content 1 (edited) | 1 | +----+-----------------------------+------------+ ,并为所有记录(包括原始记录)提供值。

您的数据如下所示:

SELECT A.* from myTable as A INNER JOIN (
  SELECT max(id) as id, content_id from myTable group by content_id
) as B ON A.id = B.id 
 AND A.content_id = B.content_id

通过这种方式,您可以使用content_id作为内容的标识符,从而节省处理空值的需要

查询将如下所示:

#first
import neurolab as nl
#then
rep=10
i=0
#Number of inputs
numIN=5
#Number of neurons per layer
cap1=12
cap2=5
#Number of outputs
out=5
#create network
net = nl.net.newff([[-1, 1]]*numIN,[cap1,cap2,out])
while i<rep:
# I use train_bfgs is faster
#entradasu are the inputs and targetsu are the targets of your data
#then the network is adjusted in each iteration
    error = nl.train.train_bfgs(net,entradasu, targetsu, epochs=1, show=0, goal=0.001)
#then do some checks
    if checks==True:
        i=rep
    else
        i+=1

答案 3 :(得分:2)

试试这个:

select * from qa
where id in (
    select max(id) from qa
        group by case when edited_id is not null then edited_id
        else id end
) 
order by case 
    when edited_id is null then id 
    else edited_id end;

这是小提琴:

http://sqlfiddle.com/#!9/6018b2/10/0

<强>解释

内部查询是完成所有工作的人,外部查询仅用于排序结果。

内部查询说分组应该在包含edited_id的行上完成,它应该按edited_id分组,如果没有编辑,它应该按id分组。当然,我们要求在分组时返回max(id)

答案 4 :(得分:1)

select max(id), post_content, edited_id from post where edited_id is not null group by edited_id
union
select id, post_content, edited_id from post where edited_id is null and id not in (select edited_id from post where edited_id is not null)