Упорядочить по одному столбцу, если другой является пустым для каждого поля - PullRequest
1 голос
/ 01 октября 2011

У меня есть две таблицы: таблицы «Темы» и объединенные таблицы «Комментарии», обе из которых содержат столбцы отметок времени. Я хотел бы упорядочить список тем так, чтобы темы с последним комментарием были наверху. Однако, если у темы нет комментариев, я хочу, чтобы она была отсортирована по дате ее создания. Другими словами, я пытаюсь сделать так, чтобы темы сортировались по дате их создания только , если у них нет комментариев - в основном, как на любом форуме. Например, если тема A (пустая) была создана после тема B (не пустая), но тема B получила ответ, который был самым последним, порядок должен быть B, A. Я не хочу все пустые темы вверху, если они старые, или внизу, если они новые.

Я пробовал оператор IF ISNULL, но он применяется ко всему столбцу, а не к каждой отдельной строке, поэтому я получаю пустые темы, застрявшие в верхней или нижней части канала.

Полагаю, мне нужно создать виртуальный столбец, содержащий только самые последние комментарии по каждой теме ...?

Вот полное утверждение:

SELECT
  $showbody,
  Topics.Title,
  Topics.id AS tID,
  Topics.Timestamp,
  Topics.MemberID,
  Users.id,
  Users.FirstName,
  Users.LastName,
  GROUP_CONCAT(DISTINCT Tags.Keywords SEPARATOR ', ') AS Tags,
  COUNT(Comments.id) AS NumberOfComments,
  (
    SELECT COUNT(Comments.id)
    FROM Comments
      LEFT JOIN Views ON Comments.TopicID = Views.TopicID
    WHERE Comments.Timestamp > Views.Visited
  ) AS NewComments
FROM Topics 
  LEFT JOIN Users ON Topics.MemberID = Users.ID 
  LEFT JOIN Comments ON Topics.id = Comments.TopicID 
  LEFT JOIN Tags ON Topics.id = Tags.TopicID 
WHERE Topics.id NOT IN (
  SELECT Tags.TopicID
  FROM Tags
  WHERE Keywords IN (
    SELECT Tag
    FROM Filters
    WHERE MemberID = '$_SESSION[SESS_MEMBER_ID]'
  )
  GROUP BY Tags.TopicID
) 
GROUP BY Topics.id 
ORDER BY Comments.Timestamp, Topics.Timestamp DESC LIMIT $plim

Любая помощь будет принята с благодарностью

Ответы [ 2 ]

2 голосов
/ 01 октября 2011

Решение 1 (демо):

-- Test initialization
CREATE TABLE Question
(
     QuestionID INT AUTO_INCREMENT PRIMARY KEY
    ,Content NVARCHAR(100) NOT NULL
    ,CreateDate DATETIME NOT NULL -- DEFAULT NOW()
);

CREATE TABLE QuestionComment
(
     QuestionCommentID INT AUTO_INCREMENT PRIMARY KEY
    ,QuestionID INT NOT NULL REFERENCES Question(QuestionID)
    ,Content NVARCHAR(100) NOT NULL
    ,CreateDate DATETIME NOT NULL -- DEFAULT NOW()
);

INSERT  Question(Content, CreateDate)
SELECT  'Question 1','2011-01-01 01:00:00'
UNION ALL
SELECT  'Question 2','2011-01-01 02:00:00'
UNION ALL
SELECT  'Question 3','2011-01-01 03:00:00';

INSERT  QuestionComment(QuestionID, Content, CreateDate)
SELECT  1,'Comment 1.1','2011-01-01 01:30:00'
UNION ALL
SELECT  2,'Comment 2.1','2011-01-01 02:30:00'
UNION ALL
SELECT  1,'Comment 1.2','2011-01-01 02:40:00'
UNION ALL
SELECT  2,'Comment 2.2','2011-01-01 02:30:00'
UNION ALL
SELECT  1,'Comment 1.3','2011-01-01 03:30:00';
-- End of Test initialization

-- Solution
SELECT  *
FROM    Question q
LEFT JOIN
(
    SELECT  qc.QuestionID, MAX(qc.CreateDate) LastCreateDate
    FROM    QuestionComment qc
    GROUP BY qc.QuestionID
) qc    ON q.QuestionID=qc.QuestionID
ORDER BY IFNULL(qc.LastCreateDate, q.CreateDate) ASC;
-- End of Solution

-- By, by
DROP TABLE QuestionComment;
DROP TABLE Question;

Результаты:

2   Question 2  2011-01-01 02:00:00 2   2011-01-01 02:30:00
3   Question 3  2011-01-01 03:00:00     
1   Question 1  2011-01-01 01:00:00 1   2011-01-01 03:30:00

Решение 2:

SELECT  *
FROM    Topics t
LEFT JOIN
(
    SELECT  c.TopicID, MAX(Timestamp) LastTimestamp
    FROM    Comments c
    GROUP BY c.TopicID 
) c ON t.id = c.TopicID 
ORDER BY IFNULL(c.LastTimestamp, t.Timestamp) ASC
2 голосов
/ 01 октября 2011

Используйте левое объединение для комментариев, сгруппируйте темы, используйте max, чтобы получить время последнего комментария, и используйте coalesce (или isnull), чтобы отсортировать дату комментария, если она есть, и дату создания в противном случае.

Пример:

select t.Title, t.CreatedDate, max(c.CreatedDate) as LastComment
from Topics t
left join Comment c on c.TopicId = t.TopicId
group by t.Title, t.CreatedDate
order by coalesce(max(c.CreatedDate), t.CreatedDate) desc
...