如何使用“Partition By”或“Max”?对于 SQL 服务器

Posted

技术标签:

【中文标题】如何使用“Partition By”或“Max”?对于 SQL 服务器【英文标题】:How to use “Partition By” or “Max”? for SQL Server 【发布时间】:2017-09-21 06:12:22 【问题描述】:

我有一个与此处针对 Oracle DB 提出的问题非常相似的问题(但我有一个 SQL Server 2012)。我作为入门者使用的示例基于here 给出的答案。

我有这四列:

[L2] ,[DateofReporting],[L3][ServerName] 或多或少在随机日期将数据添加到该表,但如果是,它将始终相同 [L2],[DateofReporting],[L3] 但具有不同的 [ServerName]

现在我想提取该数据以提供所有服务器 [ServerName],这些服务器是按 L2L3 和相关月份和年份分组的所有月份和年份最后添加的(来自 [DateofReporting] ) .

SELECT [ID],[L2],[DateofReporting],[L3],[ServerName]
      FROM (
            select *, 
            max([DateofReporting]) 
                OVER (PARTITION BY YEAR([DateofReporting]), 
                      Month([DateofReporting])) maxdate
            from [EADATAGOV].[Governance].[ToDos] 
        )max_date
      where [DateofReporting] = maxdate        

我正在逐步解决的问题是,数据不完整,它们显然是我声明中的一个错误。现在我没有看到森林的树,请你帮我清理那个 SQL 语句,或者如果有更聪明的方法,我愿意接受建议。

我正在考虑使用ROW_NUMBER() 来标记相关条目,而不是对其进行选择,但我以前从未使用过。 谢谢一月

输出示例

ID      L2   DateofReporting     L3                  name
18214   Summer  2017-09-20       cloud              BINHAS01105 <-- 
18215   Summer  2017-09-20       lightbulb          BINHAS60276 <-- 
18217   Summer  2017-09-20       lightbulb          CNAHAS62003 <-- 
15297   Summer  2017-09-15       cloud              CINHAS01105
15298   Summer  2017-09-15       boat               CINHAS60277  
15300   Summer  2017-09-15       lightbulb          DNAHAS62003
10512   Summer  2017-08-20       lightbulb          DNAHAS62003 <--

指出的那些是我希望在结果中看到的。例如。船没有比 09-15 更新的条目。


新方法:
Select [L2],
MAX([DateofReporting]) LDateOfTest
from [EADATAGOV].[Governance].[ToDos]
group by [L2], YEAR([DateofReporting]), Month([DateofReporting]) ,[DType] 
having DType= 'test'
order by LDateOfTest desc, L2 desc

这为我(正确地)提供了每个月每个 L2 的最新日期。现在理论上我应该能够在 L2 和 LDateOfTest 匹配的同一个表上使用另一个查询。 我对子选择的想法不起作用,因为我只能通过一个标准,而不是两个。但我不知道它是如何工作的,你能帮我加入吗(?)?

【问题讨论】:

输入的示例输出将有助于获得更有意义的响应。 我在原始问题中添加了一个输出示例。 包括样本数据,然后是你得到的结果与预期的结果。 【参考方案1】:

很难理解您的请求,因为您没有发布任何示例数据(输入)。 据我了解,可能我们可以从这个查询开始。你能试试吗,请告诉我?

SELECT ID
    ,L2
    ,DATEOFREPORTING
    ,L3
    ,SERVERNAME
FROM(
    SELECT ID
        ,L2
        ,DATEOFREPORTING
        ,L3
        ,SERVERNAME
        ,ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY DATEOFREPORTING DESC) RN
    FROM TODOS
    ) A
WHERE RN = 1;

【讨论】:

在 ORDER BY 中添加了 DESC【参考方案2】:

Select [ID],[L2],[DateofReporting],[L3],[ServerName] From( Select [ID],[L2],[DateofReporting],[L3],[ServerName], Row_NUmber() Over(Partition BY [ServerName],[L3] Order BY [DateofReporting] Desc) as Row_Num from [EADATAGOV].[Governance].[ToDos] ) Temp Where Row_Num = 1

【讨论】:

thx,这使它真正接近,但它也列出了我的 CINHAS60277 服务器名。对我来说,这很可能对我想要实现的目标不精确。我想提取所有在最后一天输入的服务器,无论它们是否是在该月的前一天输入的。 换句话说,为每个 L2、L3 显示在该月的最后一个日期为该 L2、L3 组合输入的服务器名称。并在之前的所有月份和年份中展示这一点。【参考方案3】:

这是我经过几个小时的努力后想出的解决方案。我不得不彻底改变我的方法。

IF OBJECT_ID('tempdb..#tmp_table') IS NOT NULL DROP TABLE #tmp_table

Select [L2],
MAX([DateofReporting]) LDateOfTest
into  #tmp_table --(L2t, LDateOfTest)
from [EADATAGOV].[Governance].[ToDos]
group by [L2], YEAR([DateofReporting]), Month([DateofReporting]) ,[DType] 
having DType = 'test'
order by LDateOfTest desc, L2 desc

SELECT [ID]
      ,[EADATAGOV].[Governance].[ToDos].[L2] L2f
      ,YEAR([DateofReporting]) YoT, Month([DateofReporting]) MoT
      ,[L3]
      ,[ServerName]
  FROM [EADATAGOV].[Governance].[ToDos] 
  right join #tmp_table tt on tt.L2 = [EADATAGOV].[Governance].[ToDos].[L2] and   tt.LDateOfTest = ToDos.DateofReporting
  where DType = 'test' 
  order by DateofReporting desc, L3 asc
  DROP TABLE #tmp_table

这可能不是最漂亮的解决方案,但它让我得到了我希望的结果。

【讨论】:

以上是关于如何使用“Partition By”或“Max”?对于 SQL 服务器的主要内容,如果未能解决你的问题,请参考以下文章

等效于 OBIEE 中的 max() keep (partition by .. order by ..)

Sql Server Max() over partition by - 翻译成 MySql

Max a Sum of a partition by

如何在不使用 GROUP BY 或 PARTITION BY 的情况下对 Oracle SQL 中的数据进行分组

over(partition by)开窗函数的使用

不能在同一个查询中使用 Partition by 和 select *