1

这个太让我挠头了!基本上,我需要显示位置列表、存储在那里的当前项目以及拥有它的人。我创建了 4 个表,并用数据填充了这些表。

设置:MSSQL 2008

我正在寻找的是来自 tbl_locationHistory 的项目和所有者的“Top(1)”,因为在每个位置的任何时候都只能有一个项目或一个所有者。请记住,tbl_locationHistory 可能有多个数据位,我只需要为每个数据提取最新的 ID(例如,历史表中当前可用的最高 ownerID、最高 itemID)。

tbl_location

locID 位置名称

tbl_item

itemID itemName

tbl_owner

所有者 ID 所有者名称

tbl_locationHistory

locHistID locID itemID ownerID dateModified

我尝试将所有这些表与连接连接在一起。但是我意识到这行不通,因为我没有拉回“所有者”或“物品”的最高 ID,因此显示的数据将不准确。

我想到的一件事是我应该将历史表分成两部分:1 x 所有者到位置和 1 x 项目到位置 - 但是我现在处于 SQL 的极限,所以可以用一些正确方向的指针来做因为不知道该怎么做。

因此,即使我必须分解历史记录表,我也需要帮助。

2012 年 1 月 11 日更新

好的,我将在这里粘贴一些代码。

我是一个老派的经典 ASP 编码器.....还需要继续前进!我正在使用经典的 asp 和 MSSQL 来创建这个应用程序。我也在使用dreamweaver,因此希望将查询放在其中,这样我就可以使用DW CS6中的“绑定”功能。

这是我的原始查询:

SELECT DISTINCT p.pID, p.cliID, p.pNo, p.pName, p.dtCommissioned,     
p.description, ps.plotStatus, pt.plotType, o.oSalutation, o.oFname, o.oSname, man.manName, 
mod.model, sl.width, sl.length, sl.yr
FROM history AS ph INNER JOIN owners AS o ON ph.ownerID   
= o.ownerID INNER JOIN StockList AS sl ON ph.stockID = sl.stkID   
INNER JOIN manufacturers AS man ON sl.make = man.manID 
INNER JOIN models AS mod ON sl.model = mod.cID FULL OUTER   
JOIN plotType AS pt RIGHT OUTER JOIN                       
plots AS p ON pt.plotTypeID = p.plotType LEFT OUTER JOIN                       
plotStatus AS ps ON p.pStatus = ps.plotStatusID ON ph.plotID = p.pID
WHERE (p.cliID = value)
ORDER BY p.pNo

现在,当我意识到我没有正确地在历史表中查找“stockID”的最高 HistoryID 以及“ownerID”的最高 plotHistoryID 时,我开始研究如何为每个 ID 执行“子查询”。 .....这就是我卡住的地方。

我已经尝试了一些类似的东西:

Select p.pID, p.cliID, p.pNo, p.pName, p.dtCommissioned,     
p.description, ps.plotStatus, pt.plotType, o.oSalutation, o.oFname, o.oSname, man.manName, 
mod.model, sl.width, sl.length, sl.yr
(Select top 1 ph.plotHistoryID, ownerID
FROM History AS ph
order by ph.plotHistoryID desc)
THEN JOINING ETC
THEN DO ANOTHER SUBQUERY FOR THE OWNER ETC

但是我无法让它工作,但我现在超出了与子查询和联接相关的 SQL 水平。

输出显示将是:

地块号 | 地块名称 | 情节类型 | 地块状态 | 当前所有者 | 当前库存

每个 Plot No's/Names/Type/Status 都将填充我需要显示的数据。如果所有者\当前股票为空白,我有一个 IF 语句,说“没有所有者”或“没有找到股票”。

然后,用户将能够单击行末尾的“查看”链接并查看绘图/位置的详细信息,并将 pID 通过 QueryString 传递到下一页。

这有帮助吗?我现在有点绝望了!哈哈

4

1 回答 1

0

您可以使用该ROW_NUMBER功能来帮助仅获取每个位置的最新历史事件,然后使用它来加入所有者和项目:

WITH LocationHistoryExt AS
(   SELECT  LocID, 
            ItemID, 
            OwnerID,
            DateModified,
            [RowNumber] = ROW_NUMBER() OVER(PARTITION BY LocID ORDER BY DateModified DESC)
    FROM    tbl_LocationHistory
)
SELECT  l.LocName,
        i.ItemID,
        o.OwnerName,
        lh.DateModified
FROM    tbl_Location l
        INNER JOIN LocationHistoryExt lh
            ON l.LocID = lh.LocID
            AND RowNumber = 1 -- ONLY LATEST EVENT
        INNER JOIN tbl_Item i
            ON lh.ItemID = i.ItemID
        INNER JOIN tbl_Owner o
            ON o.OwnerID = lh.OwnerID

编辑 - 添加解释

顶部是公共表表达式(CTE),在这种情况下,它只是将子查询移出主查询的一种方式,所以

WITH CTE AS
(   SELECT  A, B, C
    FROM    T
)
SELECT  *
FROM    CTE

和刚才执行的完全一样

SELECT  A, B, C
FROM    T

CTE 中的ROW_NUMBER将根据其中的ORDERandPARTITION子句为每个历史事件分配一个行号,因此在 tbl_LocationHistory 中给出以下示例数据:

locHistID | locID | itemID | ownerID | dateModified
----------+-------+--------+---------+--------------
    1     |   1   |   1    |   1     |  20121001
    2     |   1   |   4    |   2     |  20121002
    3     |   1   |   3    |   1     |  20121003  <-- LATEST FOR LocID 1
    4     |   2   |   5    |   2     |  20121002
    5     |   2   |   1    |   2     |  20121004
    6     |   2   |   2    |   3     |  20121005  <-- LATEST FOR LocID 2

我假设您要做的是检索每个位置 ID 的最新行,并获取与该行关联的 itemID 和 OwnerID,因此解构ROW_NUMBER函数:

ROW_NUMBER() OVER(PARTITION BY LocID ORDER BY DateModified DESC);

这将为您的数据中的每一行分配一个行号,每个LocID( PARITION BY locID) 再次从 1 开始,它将从具有最新修改日期 ( ORDER BY DateModified DESC) 的记录开始编号为 1。将此应用于您将获得的示例数据:

locHistID | locID | itemID | ownerID | dateModified | RowNumber
----------+-------+--------+---------+--------------+---------------
    1     |   1   |   1    |   1     |  20121001    | 3
    2     |   1   |   4    |   2     |  20121002    | 2
    3     |   1   |   3    |   1     |  20121003    | 1
    4     |   2   |   5    |   2     |  20121002    | 3
    5     |   2   |   1    |   2     |  20121004    | 2
    6     |   2   |   2    |   3     |  20121005    | 1

这是在我的查询中在 CTE 中检索的内容,然后当我加入它时,我添加了 that RowNumber = 1,这意味着只返回最新的行

FROM    tbl_Location l
        INNER JOIN LocationHistoryExt lh
            ON l.LocID = lh.LocID
            AND RowNumber = 1 -- ONLY LATEST EVENT


locHistID | locID | itemID | ownerID | dateModified | RowNumber
----------+-------+--------+---------+--------------+---------------
    3     |   1   |   3    |   1     |  20121003    | 1
    6     |   2   |   2    |   3     |  20121005    | 1

其余的只是正常加入,以从上述 2 行中获取适当的位置、所有者和项目。

我希望这现在更有意义。如果不让我知道,我将尝试解释任何其他内容。

编辑 2 - 占空字段

我稍微改变了 select 的顺序,改成INNER JOINLEFT JOIN,但是主体还是一样的:

WITH LocationHistoryExt AS
(   SELECT  LocID, 
            ItemID, 
            OwnerID,
            DateModified,
            [RowNumber] = ROW_NUMBER() OVER(PARTITION BY LocID ORDER BY DateModified DESC)
    FROM    tbl_LocationHistory
)
SELECT  [LocationName] = COALESCE(l.LocName, 'No Location'),
        [ItemName] = COALESCE(i.ItemName, 'No Item'),
        [OwnerName] = COALESCE(o.OwnerName, 'No Owner'),
        lh.DateModified
FROM    LocationHistoryExt lh
        LEFT JOIN tbl_Location l
            ON l.LocID = lh.LocID
        LEFT JOIN tbl_Item i
            ON lh.ItemID = i.ItemID
        LEFT JOIN tbl_Owner o
            ON o.OwnerID = lh.OwnerID
WHERE   RowNumber = 1 -- ONLY LATEST EVENT
于 2012-10-30T12:38:07.147 回答