#sql #sql-server
Вопрос:
Вот моя ситуация: у меня есть 2 таблицы, таблицы вопросов и ответов, обе из которых содержат столбец post_date. Я хочу получить количество вопросов и ответов за последние 7 дней, независимо от того, равно ли количество 0. Обратитесь к этому для получения желаемого результата
Я попробовал следующий код:
SELECT CONVERT(varchar, DATEADD(DAY,0, DATEDIFF(day,0, post_date)),23) AS q_date, COUNT(id) AS q_count
FROM [Question]
WHERE post_date >= DATEADD(day,-7, GETDATE())
GROUP BY DATEADD(DAY,0, DATEDIFF(day,0, post_date))
UNION
SELECT CONVERT(varchar, DATEADD(DAY,0, DATEDIFF(day,0, post_date)),23)AS a_date, COUNT(id) AS a_count
FROM [Answer]
WHERE post_date >= DATEADD(day,-7, GETDATE())
GROUP BY DATEADD(DAY,0, DATEDIFF(day,0, post_date))
Но в итоге количество вопросов и ответов сливается в одну колонку. Кроме того, результат отображается не для каждого дня, а только для дней, в которых существует счетчик. Выходные данные показаны, как показано ниже:
q_date q_count
---------- -------
2021-06-11 1
2021-06-12 1
2021-06-13 1
2021-06-13 2
2021-06-14 1
Любые предложения будут высоко оценены!
Решение
Решение, предложенное @Gordon, отлично подходит для этого результата:
date q_count a_count
---------- ------- -------
2021-06-11 1 0
2021-06-12 0 1
2021-06-13 2 1
2021-06-14 0 1
Для отображения за все 7 дней, даже если в течение нескольких дней данных нет, это способ:
;WITH DateTable
AS
(
SELECT DATEADD(day,-6, CONVERT(date, GETDATE())) AS [DATE]
UNION ALL
SELECT DATEADD(dd, 1, [DATE])
FROM DateTable
WHERE DATEADD(dd, 1, [DATE]) <= CONVERT(date, GETDATE())
)
SELECT COALESCE(ques.date, ans.date) as date,
COALESCE(ques.q_count, 0) as q_count,
COALESCE(ans.a_count, 0) as a_count
FROM
(SELECT dt.[DATE], COUNT(q.id) as [Q_COUNT]
FROM [DateTable] dt
LEFT JOIN [Question] q
ON dt.[DATE] = CONVERT(date, q.post_date)
GROUP BY dt.[DATE]) ques
FULL JOIN
(SELECT dt.[DATE], COUNT(a.id) as [A_COUNT]
FROM [DateTable] dt
LEFT JOIN [Answer] a
ON dt.[DATE] = CONVERT(date, a.post_date)
GROUP BY dt.[DATE]) ans
ON ques.DATE = ans.DATE
Выход:
date q_count a_count
---------- ------- -------
2021-06-10 0 0
2021-06-11 1 0
2021-06-12 0 1
2021-06-13 2 1
2021-06-14 0 1
2021-06-15 0 0
2021-06-16 0 0
Наконец, большое СПАСИБО @Gordon за то, что развеял мои сомнения!
Ответ №1:
Использовать JOIN
, FULL JOIN
на самом деле:
SELECT COALESCE(q.date, a.date),
COALESCE(q.q_count, 0) as q_count,
COALESCE(a.a_count, 0) a a_count
FROM (SELECT CONVERT(date, post_date) as date, COUNT(id) AS q_count
FROM [Question]
WHERE post_date >= DATEADD(day, -7, CONVERT(date, GETDATE()))
GROUP BY ONVERT(date, post_date)
) q FULL JOIN
(SELECT CONVERT(date, post_date) as date, COUNT(id) AS a_count
FROM [Answer]
WHERE post_date >= DATEADD(day, -7, CONVERT(date, GETDATE()))
GROUP BY CONVERT(date, post_date)
) a
ON a.date = q.date;
В вашем коде есть пара проблем:
- Вы можете просто преобразовать дату/время в a
date
, чтобы удалить компонент времени. Гораздо лучший подход, чем преобразование в строку. GETDATE()
имеет временную составляющую, поэтому сравнение сGETDATE()
не делает того, что вы (вероятно) намереваетесь).
Комментарии:
1. Привет, спасибо за ваш ответ! Он показывает только даты, в которых число q и число a не равны 0. Как, если я хочу отобразить дату, даже если оба счетчика равны 0?
2. @lsx . . . Это с помощью
full join
. Он должен показывать строки, в которых либо нет0
.