Sql-Server

計數存在於之前而不存在於之後和之後但不存在於之前的行數

  • January 16, 2021

我有一個 Azure SQL 數據庫,一個包含 3 個相關列的表:品牌、ID 和月/年,還有一個臨時表,它簡單地列出了帶有 ID 的月/年。

該表顯示了該給定月份的所有活動 ID 的列表。

Month/Year 是一個日期戳列,日期為月份的第一個。ID 列只是一個 ID。

目標是有一個輸出,每個月將顯示本月活躍但下個月不活躍的所有記錄的計數(流失)和上個月不活躍但活躍的 ID在這個月(新),並按品牌和月份分組,所以:

品牌 | 流失 | 新 | 第 1 個月

| 10 | 12 | 2019-12-01

2 | 11 | 9 | 2019-12-01

我還應該注意到 Table1 有 1900 萬行。

我嘗試了以下程式碼:

Declare @Id int
declare @my date

set @Id = 300
set @my = '2019-12-01'

select t1.[brand],
count(c.[ID]) as [churn],
count(n.[ID]) as [new],
t1.[month/year]
from Table1 T1

left join Table1 c on
c.[ID] = t1.[ID] and c.[ID] not in (select [ID] from Table1 where [Month/Year] = (select [month/year] from Temp_Date where id = (@Id +1)))
left join Table1 n on
n.[ID] = T1.[ID] and n.[ID] not in (select [ID] from Table1 where [Month/Year] = (select [month/year] from Temp_Date where id = (@Id -1)))

where t1.[Month/Year] = @my
group by t1.[Brand], t1.[Month/Year]

儘管它產生了輸出,但我認為它不正確,而且花了很長時間,這可能是由於我在聯接中自由使用了子查詢。

我的問題是 2 倍 - 有人可以幫助以更好的方式計算行數並加入它們嗎?有沒有更好的方法可以在沒有這麼多子查詢的情況下做到這一點?

通常,您應該包含生成表模式並用數據填充它們的腳本。(同樣對於性能問題,您也應該包括執行計劃。)如果沒有真實數據,我無法進行大量測試,但我相信此查詢應該會提高您所看到的性能:

DECLARE @my DATE = '2019-12-01'
DECLARE @nextMonthYear DATE = DATEADD(MONTH, 1, @my)
DECLARE @prevMonthYear DATE = DATEADD(MONTH, -1, @my)

SELECT CurrentMonth.Brand, SUM(CASE WHEN NextMonth.ID IS NULL THEN 1 ELSE 0 END) AS Churn, SUM(CASE WHEN PreviousMonth.ID IS NULL THEN 1 ELSE 0 END) AS New, CurrentMonth.MonthYear
FROM Table1 AS CurrentMonth
LEFT JOIN Table1 AS NextMonth
   ON NextMonth.MonthYear = @nextMonthYear
   AND CurrentMonth.ID = NextMonth.ID  
LEFT JOIN Table1 AS PreviousMonth
   ON PreviousMonth.MonthYear = @prevMonthYear
   AND CurrentMonth.ID = PreviousMonth.ID  
WHERE CurrentMonth.MonthYear = @my
GROUP BY CurrentMonth.Brand, CurrentMonth.MonthYear

這也比一堆子查詢簡單得多(開發人員可以閱讀和 SQL Server 解析)。您可能是對的,不需要的額外加入子查詢是您的性能問題的根源(但我無法在沒有看到執行計劃的情況下驗證這一點)。

上面的查詢所做的是LEFT JOIN在其自身上使用 a to Table1 兩次(一次用於 the PreviousMonth,一次用於 the NextMonth),ID以獲取與 . 匹配和不匹配的所有記錄CurrentMonth。然後使用內部SUM()帶有CASE語句的聚合函式,我們可以只總結NULLs(在andIDCurrentMonth不存在的情況)以獲得 and 的計數,並按and分組。PreviousMonth``NextMonth``New``Churn``Brand``MonthYear``CurrentMonth

引用自:https://dba.stackexchange.com/questions/283286