سؤال

I have a bit of a strange question. First let me tell you i cannot change the way the database is made. Some people before me made a really good job of messing some things up pretty bad.

Its a news site and there are editors in that can edit the news posts that others post. also editors can post news them self.

Now the question.

I have a table for news.

id   |  news_username    (who post news)


news_text Table

news_id  |  username  |  news_text   

(Here user: can be editor of the news or a person who  posted news)

User Table

username |  title 

In that table there is a news 'id' and a news 'username'. The username being the username of the user posting the news. there are also allot more fields inside the table but they are not important.

Then there is a table news_text and within it the text for the news is placed. This table has a 'news_id' and 'username' field. This time the username is the field of the person who posted the news OR the username of the user that edited the post.

Then i have a user table with also a 'username' field and a 'title' field with the title for the user. In this

Hope your still with me.

In short if a user posts a news article the text will be inside the 'news_text' table and when an editor edits the post the altered text will be inserted as a new text for the same article. This is done to let the original poster see what was altered to his post.

now comes my challenge. I need to figure out how i can get the number of edits that an editor made. BUT because the editor itself can post news that means that i need to search for all news where the username is not equal to the original poster and where it is look for duplicates in the news_text table to see of the editor has edited his own post.

i really hope people understand a little of what i need to do. hope you can help me.


in the comment Marcus Adams pointed me at the how the latest edit was used on the website.

This is don through a date/time field. When an edit is placed the edit will be inserted into the news_text field and there will be date/time stamp for the new edit. And with that it will determine witch text to grab for the news item.

hope this is clear

هل كانت مفيدة؟

المحلول

If I understand correctly, something like this should give the total number of edits all users have made but only where they were on posts that weren't themselves

SELECT
    user.*,
    COUNT(*) AS edits

FROM user

// Join posts that aren't this users
INNER JOIN news
ON news.username != user.username

// Join edits for the above posts that are this users
INNER JOIN news_text
ON news_text.news_id = news.id
AND news_text.username != user.username

And with a placeholder if you want to select a specific news article

SELECT
    user.*,
    COUNT(*) AS edits

FROM user

// Join posts that aren't this users
INNER JOIN news
ON news.username != user.username
AND news.id = [[SPECIFIC ID]]

// Join edits for the above posts that are this users
INNER JOIN news_text
ON news_text.news_id = news.id
AND news_text.username != user.username

Or maybe if you want to see how many edits a specific user has done on a specific article

SELECT
    user.*,
    COUNT(*) AS edits

FROM user

// Join posts that aren't this users
INNER JOIN news
ON news.username != user.username
AND news.id = [[SPECIFIC ID]]

// Join edits for the above posts that are this users
INNER JOIN news_text
ON news_text.news_id = news.id
AND news_text.username != user.username

WHERE user.username = [[SPECIFIC USERNAME]]

EDIT Alternative approach, if you want to count up all posts made by a user that ARE NOT original posts i.e. all edits, even if they are editing their own post

SELECT
    user.*,
    news.*,
    COUNT(*)-IF(news.username=user.username,1,0) AS edits
FROM user

// This join will give us all posts made by user
INNER JOIN news_text
ON news_text.username = user.username

// Also join the news id
INNER JOIN news
ON news_text.news_id = news.id

GROUP BY user.username, news.id

This will return 1 row per user per news.id counting the number of edits a user has made against it, so to take this and return totals you could instead do this to return the number of edits performed by a single user by name

SELECT
    username,
    sUM(edits)
FROM (
    SELECT
        news_text.username.username,
        COUNT(*)-IF(news.username=news_text.username,1,0) AS edits
    FROM news_text
    ON news_text.username = [[USER TO CHECK]]

    // Also join the news id
    INNER JOIN news
    ON news_text.news_id = news.id

    GROUP BY news.id
)

نصائح أخرى

I would suggest that the easiest way to do this is in two queries:

One to find the total number of changes made by a user

e.g. SELECT COUNT(*) FROM news_text WHERE username = {USERNAME} GROUP BY username

And then one to find the total posts created by that user

e.g. SELECT COUNT(*) FROM news WHERE username = {USERNAME} GROUP BY username

And subtract one from the other.

Or do queries for all users and just take out the ones you need. (Or combine them into one query if you really want).

As I understand it, you have duplicate news_text rows for a particular news item (news_id). Also, you have an edit_date field on news_text table, and you're getting the news_text with the latest edit_date to get the latest version of the news item.

I also understand that you want the to get the number of edits from each user, excluding self-edits.

Here's one solution. This is for a particular user:

SELECT COUNT(*) AS edits
FROM user u
JOIN news n
  ON n.username <> u.username
JOIN news_text nt1
  ON nt1.news_id = n.news_id
  AND nt1.username = u.username
JOIN news_text nt2
  ON nt2.news_id = n.news_id
  AND nt2.edit_date < nt1.edit_date
  AND nt2.username <> u.username
LEFT JOIN news_text nt3
  ON nt3.news_id = n.news_id
  AND nt3.edit_date > nt2.edit_date AND nt3.edit_date < nt1.edit_date
WHERE u.username = 'myuser'
  AND nt3.news_id IS NULL
  • First, it gathers all the news items that weren't authored by the user (ON n.username <> u.username)
  • Then it gathers all the news_texts for each of those news items that our user edited (ON nt1.news_id = n.news_id AND nt1.username = u.username)
  • Then it gathers all the previous versions for the above that are from other users (ON nt2.news_id = n.news_id AND nt2.edit_date < nt1.edit_date AND nt2.username <> u.username)
  • Then it gathers any versions between the current one and the previous one, for exclusion later (ON nt3.news_id = n.news_id AND nt3.edit_date > nt2.edit_date AND nt3.edit_date < nt1.edit_date)
  • Then it filters for our user (WHERE u.username = 'myuser')
  • Then it filters out edits that were in between the current and the previous, ensuring we only have the version just prior (nt3.news_id IS NULL)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top