按人称排名前十位

时间:2017-02-22 00:07:36

标签: sql sql-server

我遇到了障碍,似乎无法解决这个问题。我怀疑答案是盯着我看,但似乎无法将我的大脑包裹起来,我无法在线找到解决方案。

我试图找到每个员工在给定范围内每天完成的最后一个订单。问题是订单号不是顺序的,所以我不能只使用MAX()函数来找到它。最后,我不需要任何除了 OrderNums列表(每天每个员工的最后一个),因为这将提供给另一个查询。

这是我到目前为止所拥有的:

SELECT      
    (SELECT USERNAME FROM EMPLOYEES WHERE TechID = Invoices.TechID1) AS "Tech"
            ,CONVERT(date, OrderDate) AS "OrderDate"
        FROM Invoices
                WHERE OrderDate BETWEEN CONVERT(date, DATEADD(day, -60, GETDATE())) AND CONVERT(date, GETDATE())
        GROUP BY
            TechID1, OrderDate

        ORDER BY    
            "Tech" DESC, OrderDate DESC

每天为每位员工返回一行,这很好,但我无法弄清楚如何指定每天的最后一个订单号。最好的字段是TimeOut(发票完成的时间),所以我一直试图在SELECT子句中添加一行,如

(SELECT TOP 1 OrderNum FROM Invoices ii Where ii.TechID1 = Invoices.TechID1 AND ii.OrderDate = Invoices.OrderDate ORDER BY TimeOut DESC)

但这并不是一致的似乎应该有一种更简单的方法来做到这一点。看起来您应该只能将OrderNum添加到SELECT子句中但会引发错误(42000 - [SQL Server] Column' Invoices.OrderNum'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句。)

有什么建议吗?

P.S。你们真棒。我通过搜索这个网站得到了很多的问题。我现在还不能回复,因为我太绿了,所以我现在就说谢谢了!

- 编辑 -

Gordon Linhoff - 感谢您的建议。这很有帮助,但它只能为每个人返回几个结果,并且我们期望在60天内更接近40。我会对这个操作进行一些挖掘,因为我不知道这是一件事。我还不熟悉SQL。

McNets ydoow - 我不确定您想要的所有详细信息,但希望这会有所帮助:

发票表

  • LocationID
  • InvoiceNum
  • WorkDate
  • 超时
  • TechID1
  • (其他列的加载在这里可能没什么用。)

EmployeesTable

  • 用户名
  • TechID
  • (其他列的加载在这里可能没什么用。)

如果这有帮助,当前查询看起来像这样:

SELECT
    ...
FROM Invoices WHERE 
    OrderNum IN (
        SELECT "Last OrderNum" FROM 
        (SELECT 
            (SELECT TOP 1 OrderNum FROM PestPac.dbo.INVOICES WHERE (TechID1 = Employees.TechID OR TechID2 = Employees.TechID)  
                    AND NOT (OrderNum IS NULL)
                    AND NOT (InvoiceType = 'NS') --Not Serviced
                    AND VOID = 0 --Not Voided
                    AND CONVERT(date,WorkDate)= CONVERT(date, DATEADD(day, -7, GETDATE()))
                    AND NOT (OrderType = 'NS') ORDER BY WorkDate DESC) AS "Last OrderNum" 
                    FROM Employees
                    WHERE
                        AND Employees.active = 1 
        ) todayMinusSeven)
OR
    OrderNum IN (...) todayMinusSix)
OR
    OrderNum IN (...) todayMinusFive)
OR
    OrderNum IN (...) todayMinusFour)
OR
    OrderNum IN (...) todayMinusThree)
OR
    OrderNum IN (...) todayMinusTwo)
OR
    OrderNum IN (...) todayMinusOne)

基本上,我使用针对employees表的子查询来获取每个人在给定日期完成的最后一个订单号,然后在仅更改目标日的情况下重复相同的查询。这给了我7个订单号列表,我转过来用来过滤Invoice表,然后从那里得到我想要的数据。对于文明时代来说,它是非常不优雅的武器。如上所述,此更改的目标是使用 Workdate BETWEEN X和Y 子句创建一个子查询。

1 个答案:

答案 0 :(得分:1)

嗯。我想你可以使用row_number()

SELECT i.*
FROM (SELECT i.*,
             ROW_NUMBER() OVER (PARTITION BY TechId1, CONVERT(date, OrderDate) ORDER BY OrderDate DESC) as seqnum
      FROM Invoices i
      WHERE OrderDate BETWEEN CONVERT(date, DATEADD(day, -60, GETDATE())) AND CONVERT(date, GETDATE())
     ) i
WHERE seqnum = 1;

这将选择整行。您可以选择所需的特定列。