SQL为每行选择TOP 10

时间:2014-06-05 12:41:08

标签: sql sql-server sql-server-2005

我在选择以下代码中每行的顶部时遇到一些问题:

这将基于LineNoID,即行。

SELECT TOP 10

        DTM.[LineNoID]          as [Line ID],
        DTM.[Fault Code]        AS [DTM Fault Code],
        DTFC.[Fault Code]       AS [DTFC Fault Code], 
        COUNT(DTM.[Fault Code]) AS [Fault Code Occurences], 
        DTFC.[Fault Name],
        SUM(DTM.[Minutes Down]) AS [Total Minutes Down]

FROM

        DTMain          AS DTM,
        DTFaultCodes    AS DTFC,
        DTLine          AS DTL

WHERE   

        DTM.[Fault Code] = DTFC.[Fault Code]

AND     

        DTM.LineNoID = DTL.[LineNoID]

AND

        DTFC.[Category] = 'E'

GROUP BY 
            DTM.[LineNoID],
            DTM.[Fault Code],
            DTFC.[Fault Code],
            DTFC.[Fault Name]           

ORDER BY [Total Minutes Down] DESC

我查看了其他几篇帖子,并且正在努力将它们“转换”为我的代码。任何帮助将不胜感激!

谢谢, 大卫


更新了查询:

SELECT
        [Line ID],
        [DTM Fault Code],
        [DTFC Fault Code],
        [Fault Code Occurences],
        [Total Minutes Down]
FROM
  (
SELECT
        ROW_NUMBER() OVER (PARTITION BY DTM.[LineNoID] ORDER BY SUM([Minutes Down] AS [Total Minutes Down]) DESC) [Line ID],
        DTM.[LineNoID]          AS [Line ID],
        DTM.[Fault Code]        AS [DTM Fault Code],
        DTFC.[Fault Code]       AS [DTFC Fault Code], 
        COUNT(DTM.[Fault Code]) AS [Fault Code Occurences], 
        DTFC.[Fault Name]
FROM
        DTMain          AS DTM,
        DTFaultCodes    AS DTFC,
        DTLine          AS DTL
WHERE
        DTM.[Fault Code] = DTFC.[Fault Code]
AND
        DTM.LineNoID = DTL.[LineNoID]
AND
        DTFC.[Category] = 'E'
GROUP BY
            DTM.[LineNoID],
            DTM.[Fault Code],
            DTFC.[Fault Code],
            DTFC.[Fault Name]
  ) s
WHERE [Total Minutes Down] <= 10

ORDER BY [Total Minutes Down] DESC

显示“'SUM'不是公认的内置函数名。”在运行上面的时候。

抱怨缺乏知识!

1 个答案:

答案 0 :(得分:0)

以下是基于我自己的数据库中的日志记录表的示例(SQL 2012):

SELECT 
    IdentifyingValue,
    GroupingValue,
    RowNum,
    SummedValue
FROM 
  (
    SELECT  
        TrgTabName AS IdentifyingValue, 
        CAST(JobDate AS DATE) GroupingValue, 
        ROW_NUMBER() OVER (PARTITION BY TrgTabName ORDER BY SUM(TrgTabNewRows) DESC) RowNum,
        SUM(TrgTabNewRows) SummedValue
    FROM DWA_JobTableCount
    GROUP BY TrgTabName, CAST(JobDate AS DATE)
  ) s
WHERE RowNum <= 3

您可以使用基础SELECT语句替换示例s子查询,并修改ROW_NUMBER()函数以将LineNoID用作PARTITION BY和您的[Total Minutes Down]ORDER BY DESC。然后修改外部查询以检索所需的列,并修改外部WHERE子句以获取所需的RowNum计数。

=============================================== ===================================

修改 你很好地尝试了合并代码,但是有一些错误。其中一个是我的:我没有注意到你在原始查询中使用了SUM()函数,我告诉你在ROW_NUMBER()函数中使用该字段。在ROW_NUMBER()这样的窗口函数中使用任何类型的聚合是不允许的,所以必须发生的是三层查询,而不是我向您展示的两级查询:最低层是您的原始层(包括SUM),中间层将ROW_NUMBER()和排名添加到输出,外部添加基于ROW_NUMBER()的过滤器。

此处还有其他一些问题:您在错误定位的SUM()函数中包含别名,这可能是您收到的特定错误的原因。您还有两个名为Line ID的列,即使您尝试将其包含在Total Minutes Down中,也永远不会生成一个单独的列,为您提供SELECT的总和。 WHERE条款。最后,您的过滤器实际上仍未指向ROW_NUMBER()函数生成的列,这会伤害您。

步骤1:将分组和聚合放在嵌套查询中,将SUM添加为单独的列。当我在这里的时候,我还给你写了一些JOIN表达式的更新语法:使用这种格式,因为不再推荐使用逗号JOIN(正如marc_s在注释中指出的那样)。

第2步:添加ROW_NUMBER()函数以生成新列。这会使用列(Line IDTotal Minutes Down)生成一个名为RowNum的新列。

第3步:检索您想要的字段并过滤&#34; top&#34;十(RowNum字段有助于识别)。

请查看以下代码,并告诉我它是否适合您。我无法访问您的基表,因此我可能会错误地命名某个字段或引用错误的别名 - 由您来审核我的代码示例以确保它适合您的数据库。我相信这会产生您正在寻找的功能。

SELECT -- returns the data you wanted originally
    [Line ID],
    [DTM Fault Code],
    [DTFC Fault Code],
    [Fault Code Occurrences],
    [Fault Name],
    [Total Minutes Down]
FROM
  (
    SELECT -- adds the row number 
        [Line ID],
        [DTM Fault Code],
        [DTFC Fault Code],
        [Fault Code Occurrences],
        [Fault Name],
        [Total Minutes Down],
        ROW_NUMBER() OVER (PARTITION BY [Line ID] ORDER BY [Total Minutes Down] DESC) RowNum -- numbers, in descending order, the rows for each Line ID
    FROM
      (
        SELECT -- retrieves the base (aggregated) data used by the query
            DTM.[LineNoID]          as [Line ID],
            DTM.[Fault Code]        AS [DTM Fault Code],
            DTFC.[Fault Code]       AS [DTFC Fault Code], 
            COUNT(DTM.[Fault Code]) AS [Fault Code Occurrences], 
            DTFC.[Fault Name],
            SUM(DTM.[Minutes Down]) AS [Total Minutes Down] -- you still need this column to use in your output and RowNum
        FROM
            DTMain DTM 
             INNER JOIN -- note the new syntax
            DTFaultCodes DTFC ON
                DTM.[Fault Code] = DTFC.[Fault Code] -- this specifies what the relationship between the two tables is: please confirm this is correct.
             INNER JOIN 
            DTLine DTL ON 
                DTM.LineNoID = DTL.LineNoID
        WHERE DTFC.Category = 'E' -- this doesn't really need to be in the JOIN condition: because you are using INNER JOIN, it does the same thing in the WHERE clause.
        GROUP BY 
            DTM.[LineNoID],
            DTM.[Fault Code],
            DTFC.[Fault Code],
            DTFC.[Fault Name]           
      ) s1 -- the subquery at the first (lowest) level: think of it as a table with the data returned by the SELECT statement
  ) s2 -- the subquery at the second (middle) level
WHERE RowNum <= 10 -- the filter that controls the 'TOP n'