2016-08-27 13 views
5

Dưới đây là cấu trúc bảng:Làm cách nào để chọn phiên bản đã chỉnh sửa cuối cùng của bài đăng?

+----+-----------------------------+-----------+ 
| 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   | 
+----+-----------------------------+-----------+ 

Bây giờ tôi muốn chọn phiên bản chỉnh sửa mới nhất của mỗi bài. Vì vậy, đây là kết quả mong đợi:

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

Tôi làm như thế nào?

+0

Làm cách nào để bạn xác định "cuối cùng" và "từng bài đăng"? –

+0

@PaulSpiegel Phiên bản cuối cùng của mỗi bài đăng là phiên bản có 'id' lớn hơn so với các bài đăng khác. Ngoài ra một bài gốc là một trong đó có 'edited_id = NULL'. –

+3

Bạn nên thay đổi thiết kế db của bạn và làm cho cuộc sống của bạn dễ dàng hơn. –

Trả lời

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) 
+0

[Sẽ không hoạt động] (http://sqlfiddle.com/#!9/13236f/5). –

+0

Bạn có thể hiển thị kết quả của truy vấn này không? –

+0

Tôi đã làm .. bình luận ở trên là một câu hỏi của bạn. –

3

SQL Fiddle để xem cách nó hoạt động.

Đầu tiên chúng tôi sẽ xóa phần " (edited)" chuỗi (nếu cần) từ post_content để preapre một cột trong nhóm bằng cách, sau đó tính toán tối đa id mỗi nhóm của chúng tôi và cuối cùng gia nhập trở lại cùng một bảng để lấy giá trị cho một đặc biệt 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 

Output

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

TRƯỜNG HỢP giải thích

-- 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 
+0

Odd .. trong đó 'id = 7' nội dung là' nội dung 1 (đã chỉnh sửa) '.. Nhưng trong kết quả, trong đó' id = 7', nội dung là 'nội dung 1'. –

+0

Điểm tốt! Đã sửa. Chỉ cần thay đổi 'goo.post_content' thành' qa.post_content'. Điều này là do chúng tôi cắt bớt phần "(đã chỉnh sửa)" và do đó chúng tôi cần lấy giá trị ban đầu từ bảng giống như cách chúng ta làm cho 'edited_id' –

+0

Có vẻ tốt .. cảm ơn .. upvote –

3

này nên làm việc:

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

Nếu bạn muốn đặt hàng bởi 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

+0

Âm thanh tốt, upvote .. Chỉ cần thứ tự không giống như mong đợi ... –

+0

Không có gì về trật tự trong câu hỏi của bạn. Bạn muốn đặt hàng cái gì? –

+0

[Kết quả mong đợi.] (Http://i.stack.imgur.com/XnP2d.png) –

2

thử điều này:

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; 

và đây là fiddle:

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

Giải thích

Truy vấn bên trong là một trong những người làm tất cả công việc, truy vấn bên ngoài chỉ dành cho lệnh áp dụng các kết quả.

Truy vấn bên trong cho biết rằng việc nhóm nên được thực hiện trên các hàng có chứa edited_id, nên nhóm theo edited_id, nếu nó không được chỉnh sửa, nên nhóm theo id. Và tất nhiên, chúng tôi đã yêu cầu trả lại max(id) khi nhóm.

+0

Và đây là nhanh nhất. –

+0

Yeah .. đẹp .. cảm ơn bạn .. upvote –

+0

"Và đây là nhanh nhất." - Bạn cá cược! ;-) –

3

Giống như @PaulSpiegel được đề xuất trong các nhận xét, tôi nghĩ một thay đổi nhỏ trong cấu trúc bảng sẽ làm cho cuộc sống của bạn dễ dàng hơn nhiều.
Tôi khuyên bạn nên thay đổi edited_id bằng content_id và cung cấp giá trị đó cho tất cả các bản ghi, bao gồm cả bản gốc.

Dữ liệu của bạn sẽ trông như thế này:

+----+-----------------------------+------------+ 
| 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   | 
+----+-----------------------------+------------+ 

Bằng cách đó, bạn có thể sử dụng CONTENT_ID như một định danh của nội dung, mà giúp bạn tiết kiệm cần để đối phó với vô giá trị

Truy vấn sẽ trông giống như:

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 
+0

Âm thanh tốt .. upvote .. Nhưng bạn biết, [this] (http://stackoverflow.com/questions/39177757/how-can-i-select - phiên bản cuối cùng-edited-version-of-the-post) là câu hỏi đầy đủ của tôi. Bạn có nghĩ phương pháp tiếp cận của bạn sẽ hoạt động trên bàn trong câu hỏi đó? –

+0

@MartinAJ - vâng, nó cũng làm việc cho điều đó, tôi đoán bạn cần phải thêm cột 'type' vào truy vấn bên trong để nhận cả hai loại (cả hai cột được chọn, được sử dụng trong kết nối và cho nhóm theo) –

+0

Trong cấu trúc bảng của bạn, tôi cần đặt id của chính nó vào cột 'content_id' khi một hàng không được chỉnh sửa. Nói cách khác, làm thế nào tôi có thể chèn một hàng và đặt giá trị 'id' cũng như giá trị' nội dung' trong cùng một thời điểm? –

Các vấn đề liên quan