【问题标题】:T-SQL return MAX fieldT-SQL 返回 MAX 字段
【发布时间】:2017-10-19 10:08:02
【问题描述】:

我有这个代码:

SELECT ItemID, UserID, MAX(LogID) AS 'LatestLog'
FROM Log
WHERE UserID <> 0
GROUP BY ItemID, UserID`

现在这会将用户 ID 返回到某个项目的最新日志条目。我假设在加入另一个具有我要加入的项目 ID 的表时它会做同样的事情,如下所示:

SELECT it.ItemID, it.ItemName, UA.UserID
FROM ItemTable it LEFT JOIN
     (SELECT ItemID, UserID, MAX(LogID) AS 'LatestLog'
      FROM Log
      WHERE UserID <> 0
      GROUP BY LogID, UserID
     ) AS UA
     ON it.ItemID = UA.ItemID

这段代码会为每个修改项目的用户返回最大 LogID,而不是像我假设的那样只返回最大 LogID。我在这里错过了什么?

我还创建了一个标量函数,我将在其中输入日志表 LogID 并返回用户 ID 并且可以工作,但是在运行它之后,它会减慢速度非常糟糕,我假设这是由于从加入 ItemID 的初始表。

DECLARE @UID INT
SELECT @UID = al.UserID FROM Log al WHERE al.LogID = @theID
RETURN @UID

然后像这样使用它:

SELECT ItemID, ItemName, UDFGetModBy(MAX(UA.LogID)) FROM ItemTable it 
LEFT JOIN (SELECT ItemID, UserID, MAX(LogID) AS 'LatestLog' FROM Log WHERE UserID <> 0
GROUP BY LogID, UserID) AS UA ON it.ItemID = UA.ItemID

项目表架构包括:ItemID, ItemName, CreatedDate
日志表架构包括:LogID, ItemID (FK to Item Table), DateModified, UserID

预期的输出应该是:it.ItemID, it.ItemName, al.UserID, al.DateModified

进一步澄清:每次非系统用户 (UserID &lt;&gt; 0) 修改项目时,日志表都会保存一个新的 LogID。

也试过了:

SELECT it.ItemID, it.ItemName, UID = 
(SELECT al.UserID, MAX(al.LogID) AS 'LID' FROM Log al)  
WHERE al.UserID <> 0 AND it.ItemID = al.ItemID) 
FROM ItemTable it

但我得到一个 only one expression can be specified in the select list when the subquery is not introduced with EXISTS错误

有什么建议吗?

【问题讨论】:

  • 分享ItemLogSchemaData。预计Output
  • 我不确定您是否需要派生表来执行此操作。它会减慢它的速度,你在函数中一个一个地做它,并把它从基于集合的状态中移除。
  • 我试图回答,但意识到我们首先需要您的表定义。
  • @Leonidas199x 这在 MySql 或 SQL Server 2000 或更早版本中是正确的,但对于具有良好统计优化器(如 SQL Server 2005+、Oracle 或 DB2)的 DBMS 则不是这样。
  • @RBarryYoung 很有趣,你知道关于它的任何阅读材料吗?有兴趣了解它是如何工作的,谢谢。

标签: sql sql-server tsql ssms


【解决方案1】:

您需要在选择中过滤数据。像这样的东西(这里没有sql):

SELECT ItemID, ItemName, UDFGetModBy(MAX(UA.LogID)) FROM ItemTable it 
OUTER APPLY (SELECT ItemID, UserID, MAX(LogID) AS 'LatestLog' FROM Log WHERE 
UserID <> 0 and ItemID = it.ItemID GROUP BY ItemID, UserID)

使用 Outer Apply 可以过滤子查询中的数据。

【讨论】:

    【解决方案2】:

    最后我想你可以在子查询中这样做:

    SELECT TOP 1 * FROM ItemTable ORDER BY DESC
    

    这会抓取我正在寻找的整个“LatestLog”行。不确定它是否是最佳的,但它现在可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-05
      • 2013-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-02
      • 2010-10-19
      相关资源
      最近更新 更多