1

これは私に頭を悩ませています!基本的に、場所、そこに保管されている現在のアイテム、およびその所有者のリストを表示する必要があります。4 つのテーブルを作成し、これらにデータを入力しました。

セットアップ: MSSQL 2008

私が探しているのは、アイテムと所有者の tbl_locationHistory からの「Top(1)」です。これは、各場所で一度に 1 つのアイテムまたは 1 つの所有者しか存在できないためです。tbl_locationHistory には複数のデータが含まれる可能性があることに注意してください。それぞれの最新の ID を取得する必要があります (たとえば、履歴テーブルから現在入手できる最高の ownerID、最高の itemID)。

tbl_location

locID locName

tbl_item

itemID itemName

tbl_owner

所有者 ID 所有者名

tbl_locationHistory

locHistID locID itemID ownerID dateModified

これらすべてのテーブルを結合して結合しようとしました。ただし、「所有者」または「アイテム」のトップIDを引き戻していないため、表示されるデータが不正確になるため、機能しないことに気付きました。

私が考えたことの1つは、履歴テーブルを2つの部分に分割する必要があるということです.1つの所有者から場所へ、1つのアイテムから場所へ - しかし、私は今SQLの限界に達しているので、正しい方向のいくつかのポインタで行うことができますこれでどちらに行くかわからないので。

したがって、履歴テーブルを分割する必要がある場合でも、支援が必要になります。

2012 年 1 月 11 日更新

OK、ここにコードを貼り付けます。

私は古い学校の古典的な 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

ただし、それを機能させることはできませんでしたが、サブクエリとJOINSに関連して、SQLのレベルを超えています。

出力表示は次のようになります。

プロット番号 | プロット名 | プロット タイプ | プロット状況 | 現在の所有者 | 現在の在庫

プロット番号/名前/タイプ/ステータスのそれぞれに、表示する必要があるデータが入力されます。所有者\現在の在庫が空白の場合、「所有者なし」または「在庫が見つかりません」という IF ステートメントがあります。

ユーザーは、行の最後にある「表示」リンクをクリックして、プロット/場所の詳細を表示し、QueryString を介して次のページに pID を渡すことができます。

これは役に立ちますか?私は今、少し絶望的になっています!笑

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_NUMBERORDERは、その中のand句に応じて、各履歴イベントに行番号を割り当てますPARTITION。そのため、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);

これにより、データの各行に行番号が割り当てられます。各行は1 から始まりLocID( PARITION BY locID)、最新の更新日 ( 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 で取得されたものであり、それに参加したときに追加したものです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 行から適切な Location、Owner、および Item を取得するための通常の結合です。

これが今より理にかなっていることを願っています。そうでない場合はお知らせください。他のビットについて説明しようと思います。

編集 2 - NULL フィールドの説明

select の順序を少し変更INNER JOINしてに変更しましLEFT 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 に答える