回答
菲利克斯修復解決方案。我認爲你在第一次CTE中不應該被area
分區。你應該在第二個CTE中劃分area
,而不是按它排序。
WITH
CTE1
AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY tenant ORDER BY date desc) AS rn
FROM yourTable
)
,CTE2
AS
(
SELECT
*
,rn - ROW_NUMBER() OVER (PARTITION BY tenant, area ORDER BY rn) AS rnk
FROM CTE1
)
SELECT
tenant
,area
,date
,sales
FROM CTE2
WHERE rnk = 0
ORDER BY tenant, date desc
費利克斯的答案也會產生正確答案..你是怎麼說你的更正確的。如何影響第一次CTE的面積? @Vladimir – rickyProgrammer
@rickyProgrammer,Felix的查詢肯定會返回與我的變體不同的結果。正如我在評論中所說的,當你的數據具有'10'而不是'20'時,試着運行Felix查詢。至於,你需要哪個結果,取決於你。如果您在樣本中添加更多數據並且涵蓋不同案例的預期結果,它將有助於包括您在內的所有人。 –
的使用差距及離島的解決方案:
WITH CteIslands AS(
SELECT *,
grp = DATEADD(DAY, -ROW_NUMBER() OVER(PARTITION BY tenant, area ORDER BY date), date)
FROM yourTable
),
Cte AS(
SELECT *,
rnk = RANK() OVER(PARTITION BY tenant ORDER BY grp DESC, area)
FROM CteIslands
)
SELECT tenant, area, date, sales
FROM Cte WHERE rnk = 1
嘗試將'area'的兩個值從'20'更改爲'10',您將看到查詢不會返回您所期望的內容。 –
這是有道理的...我正在嘗試你的@Vladimir – rickyProgrammer
溶液使用Windowing Functions或the APPLY operator可能會更簡單,更高效的執行,但有些人使用這些有困難的時候,我懷疑最好的結果會利用LAG/LEAD,這是的在Sql Server 2008中不可用。因此,我提供了一個純粹基於JOIN和GROUP BY的解決方案。
首先你需要知道最近的每個租戶的日期:
SELECT tenant, MAX(date) date
FROM sample s1
GROUP BY s1.tenant
你可以用它來找到該行的area
值:
SELECT tenant, area, date
FROM sample s
INNER JOIN (
SELECT tenant, MAX(date) date
FROM sample s1
GROUP BY s1.tenant
) t on t.tenant = s.tenant and t.date = s.date
現在你可以用它來找到不具有相同區域的最近日期:
SELECT s3.tenant, MAX(date) date
FROM sample s3
INNER JOIN (
SELECT tenant, area, date
FROM sample s2
INNER JOIN (
SELECT tenant, MAX(date) date
FROM sample s1
GROUP BY s1.tenant
) j1 on j1.tenant = s.tenant and j1.date = s.date
) j2 on j2.tenant = s3.tenant and j2.area <> s3.area
GROUP BY s3.tenant
而現在您可以n使用此日期從與其中的日期爲每個租戶選擇的所有記錄更大:
SELECT s4.*
FROM sample s4
INNER JOIN (
SELECT s3.tenant, MAX(date) date
FROM sample s3
INNER JOIN (
SELECT tenant, area
FROM sample s2
INNER JOIN (
SELECT tenant, MAX(date) date
FROM sample s1
GROUP BY s1.tenant
) j1 on j1.tenant = s.tenant and j1.date = s.date
) j2 on j2.tenant = s3.tenant and j2.area <> s3.area
GROUP BY s3.tenant
) j3 on j3.tenant = s4.tenant and s4.date > j4.date
值得注意聽到我可以在嵌套的聯接重新使用表的別名,但我經常發現它如果我保持它們的獨特性,在編寫查詢時更容易跟蹤事物。您還可以通過移動嵌套查詢出來的CTE提高可讀性,這將有助於保持合理的流動,我提出:
-- Most recent date for each tenant
WITH LatestDates AS
(
SELECT tenant, MAX(date) date
FROM sample
GROUP BY tenant
),
-- the area for each tenant on that date
LatestAreas AS
(
SELECT tenant, area
FROM sample s
INNER JOIN LatestDates l on l.tenant = s.tenant and l.date = s.date
),
-- the most recent date for each tenant where the area is different
LatestDateWithChangedArea AS
(
SELECT s.tenant, MAX(date) date
FROM sample s
INNER JOIN LatestAreas l on l.tenant = s.tenant and l.area <> s.area
GROUP BY s.tenant
)
-- all records for each tenant where the date is greater than that
SELECT s.*
FROM sample s
INNER JOIN LatestDateWithChangedArea l ON s.tenant = l.tenat and s.date > l.date
正如我前面提到的,我們可以使用APPLY
運營商進一步簡化這一點:
WITH LatestDates AS
(
SELECT tenant, MAX(date) date
FROM sample
GROUP BY tenant
)
SELECT s3.*
FROM LatestDates l
INNER JOIN sample s ON s.tenant = l.tenant and s.date = l.date
OUTER APPLY (
SELECT TOP 1 tenant, date
FROM sample s2
WHERE s2.tenant = s.tenant and s2.area<>s.area
ORDER BY s2.tenant, s2.date desc
) a
INNER JOIN sample s3 ON s3.tenant = a.tenant and s3.date > a.date
(感謝這裏的其他海報以節省我一些時間把架構放在一起。)
當你在查詢中通過'date'加入時,你認爲每個房客只有一行最大日期,是嗎? –
這是正確的,但迄今爲止的所有跡象都表明,情況會如此。如果需要,我可以將這些JOIN轉換爲APPLY,以避免這種情況,但JOIN速度更快。 –
可以試試這個
//get latest date record for the tenant WITH LatestData AS (SELECT tenant, area, date FROM tenant_table as a WHERE DATE = (SELECT MAX(date) FROM tenant_table as b WHERE a.tenant = b.tenant) ), //get latest date record for the tenant with area not the latest area LatestDateWithAreaChanged AS (SELECT tenant, max(date) FROM tenant_table as c INNER JOIN LatestData as D ON c.tenant = D.tenant and c.area d.area GROUP BY tenant) //get all data where date is after the last area changed SELECT X.* FROM tenant_table as X INNER JOIN LatestDateWithAreaChanged as Y ON X.tenat = Y.tenant AND X.date > Y.date
- 1. SQL SELECT查詢
- 2. SQL SELECT查詢
- 3. SQL Select查詢
- 4. 基本的多對多sql select查詢
- 5. 基於select的多個插入查詢?
- 6. mysql的select查詢得到基於
- 7. SQL查詢基於計數
- 8. SQL查詢,基於條件
- 9. SQL查詢基於條件
- 10. SQL查詢基於序列
- 11. SQL Select子查詢
- 12. SELECT WHERE sql查詢
- 13. 從SQL SELECT查詢
- 14. Sql select count查詢
- 15. SQL SELECT查詢中
- 16. 用於select的SQL中的子查詢
- 17. SQL SELECT查詢問題
- 18. DB2 SQL SELECT基於加權
- 19. 帶有列的SQL查詢或查看取決於SELECT查詢
- 20. SQL查詢用SELECT和IF
- 21. 將SQL查詢轉換爲Access查詢 - SELECT內的SELECT
- 22. 結合sql select查詢
- 23. Sql select查詢性能
- 24. SQL查詢使與內SELECT
- 25. 的Oracle SQL SELECT查詢
- 26. SQL SELECT查詢幫助
- 27. 問題與SQL SELECT查詢
- 28. 基於子查詢
- 29. DB2中的SQL SELECT查詢
- 30. SQL SELECT查詢幫助
'SELECT TOP 4 * FROM yourTable ORDER BY [日期] DESC'? –
它並不總是前4名,區域可能會相應改變,並可能與另一位房客再次有所不同。 – rickyProgrammer
如果OP想按日期升序排序,可以類似於Felix的評論,但是像這樣'select * from(select * from(select * from table order by [date] desc)[date]' – zedfoxus