2017-11-30 3 views
0

データベースにクエリを行い、32485 ProjectNumberを共有するすべての列を取得しています。
それぞれChangeDateTimeを最大でorderIdにする必要があります。最大日付値を持つすべてのレコードを条件と一致する選択と並行して取得する

データベーステーブル:

OrderID  ProjectNumber  ChangeDateTime 
--------------------------------------------- 
1    32485  30/11/2018 
1    32485  29/11/2018 
1    32485  28/11/2018 
2    32485  30/09/2017 
2    32485  29/09/2017 
2    32485  28/09/2017 

Desierd結果:私がこれまで試してみました(しかし、私はそれが唯一最大ChangeDateTimeで1つのレコードを返し驚いていないよ何

OrderID  ProjectNumber  ChangeDateTime 
--------------------------------------------- 
1    32485  30/11/2018 
2    32485  30/09/2017 

):

SELECT TOP 1 
Orders.OrderID, 
Changes.ChangeDateTime, 
Orders.ProjectNumber 
FROM Orders 
INNER JOIN Changes ON Changes.ItemID = Orders.OrderID 
INNER JOIN LineStatusSettings ON 
Cast(LineStatusSettings.LineStatusSettingID as varchar(max)) = Changes.NewValue 
INNER JOIN LineStatuses ON LineStatuses.LineStatusID= LineStatusSettings.LineStatusID 
INNER JOIN OrderTypes ON OrderTypes.OrderTypeID = LineStatusSettings.OrderTypeID 
WHERE Orders.ProjectNumber = 32485 AND Orders.Deleted=0 
GROUP BY Orders.OrderID, 
Changes.ChangeDateTime, 
Orders.ProjectNumber 
ORDER BY Changes.ChangeDateTime DESC 
+0

左揃えのSQLは読みにくいです。 – jarlh

+0

8つの列を選択しますが、3つだけが返されます。奇妙な。 – jarlh

答えて

2

あなたはあまりにも複雑になっています。あなたが登録しよエリア内の他のものを必要とする場合は、追加した場合、出力のために考えられた行を制限する目的のために、それは

SELECT 
    Orders.OrderID, 
    Orders.ProjectNumber, 
    MAX(Changes.ChangeDateTime) 
FROM Orders 
    INNER JOIN Changes ON Changes.ItemID = Orders.OrderID 
    INNER JOIN LineStatusSettings ON Cast(LineStatusSettings.LineStatusSettingID as varchar(max)) = Changes.NewValue 
    INNER JOIN LineStatuses ON LineStatuses.LineStatusID= LineStatusSettings.LineStatusID 
    INNER JOIN OrderTypes ON OrderTypes.OrderTypeID = LineStatusSettings.OrderTypeID 
WHERE Orders.ProjectNumber = 32485 AND Orders.Deleted=0 
GROUP BY 
    Orders.OrderID, 
    Orders.ProjectNumber 

に追加することができます

SELECT 
    Orders.OrderID, 
    Orders.ProjectNumber, 
    MAX(Changes.ChangeDateTime) 
FROM Orders 
INNER JOIN Changes ON Changes.ItemID = Orders.OrderID 
WHERE 
    Orders.ProjectNumber = 32485 
GROUP BY 
    Orders.OrderID, 
    Orders.ProjectNumber 

:このクエリは、所望の出力を生成します出力への列数が増え、集計関数(min/max/avg/sum/countなど)に含まれていない場合は、それらもグループに追加する必要があります。ユニークな値の組み合わせの数が増加します

AY効率的にデータの負荷を取得し、「わずか数の列に基づいTOP x」を選択するには、このようになります:

SELECT * FROM 
(
SELECT 
    *, 
    ROW_NUMBER() OVER(PARTITION BY Orders.OrderID, Orders.ProjectNumber ORDER BY Changes.ChangeDateTime DESC) as rown 
FROM Orders 
    INNER JOIN Changes ON Changes.ItemID = Orders.OrderID 
    INNER JOIN LineStatusSettings ON Cast(LineStatusSettings.LineStatusSettingID as varchar(max)) = Changes.NewValue 
    INNER JOIN LineStatuses ON LineStatuses.LineStatusID= LineStatusSettings.LineStatusID 
    INNER JOIN OrderTypes ON OrderTypes.OrderTypeID = LineStatusSettings.OrderTypeID 
WHERE Orders.ProjectNumber = 32485 AND Orders.Deleted=0 
--ORDER BY Orders.OrderID, Orders.ProjectNumber, Changes.ChangeDateTime DESC 
)a 
WHERE 
    a.rown = 1 

このdoesntのグループデータ、それだけで一緒にすべてを結合します。次に、ROW_NUBMER句は、OrderID/PrijectNumberペアの一意の発生ごとにデータをブロックに分割し、ペアリングごとに最新の日付で1から始まり1ずつ増加するカウンタを設定します。異なるOrderID/ProjectNumberの組み合わせ(OrderID 1、ProjectNumber 1)、(OrderID 2、Project 1)は1、NoIDは1(OrderID 1、ProjectNumber 2)の1つの行番号が1になります。 )

サブクエリを単独で実行すると、どのように動作するか分かりやすくなります。isloationで実行している場合は、ORDER BY行のコメントを外すことをお勧めします。何が起こっているかを確認する(ペア設定が変更されたときにカウンタが1から再開)

+0

あなたが書いたのは "...それはおそらく行の数を増やすでしょう。なぜならそれは値のユニークな組み合わせの数を増やすからです..."あなたは他の列を抽出するためにネストされた選択を使うのが最も効率的な方法だと思いますか?それとも良い方法があるのでしょうか? – jonathana

+0

それはあなたが必要とする他の列に依存します。時々 'ROW_NUMBER()OVER(PARTITION BY x ORDER) 'を使ってたくさんのカラムがある場合には別のトリックがあります。 BY y) ' - 例を追加します。 –

+0

ありがとう!それは私にとって非常に役に立ちます。 – jonathana

0

使用TOP 1 WITH TIES

SELECT TOP (1) WITH TIES . . . 
関連する問題