2016-11-24 10 views
0

私の下のコードは正常に動作します。何それがないこと、それは、これがどのように動作するかを示すために、新しい場所これらのデータを取得するより良い方法はありますか?

select 
a.loc1 As [Location 1], 
b.loc2 as [Location 2], 
c.loc3 as [Location 3], 
d.loc4 as [Location 4] 

FROM (select distinct a.ProductNR as Loc1 
from LocationsTest a 
where a.Date= (select max(Date) from LocationsTest where a.ProductNR = ProductNR) 
AND a.Location = 1) as a 

FULL OUTER JOIN 

(select distinct a.ProductNR as Loc2 
from LocationsTest a 
where a.Date= (select max(Date) from LocationsTest where a.ProductNR = ProductNR) 
AND a.Location = 2) as b 
on a.Loc1 = b.Loc2 

FULL OUTER JOIN 

(select distinct a.ProductNR as Loc3 
from LocationsTest a 
where a.Date= (select max(Date) from LocationsTest where a.ProductNR = ProductNR) 
AND a.Location = 3) as c 
ON ISNULL(A.Loc1, b.Loc2) = c.Loc3 

FULL OUTER JOIN 

(select distinct a.ProductNR as Loc4 
from LocationsTest a 
where a.Date= (select max(Date) from LocationsTest where a.ProductNR = ProductNR) 
AND a.Location = 4) as d 
ON ISNULL(b.Loc2, c.Loc3) = d.Loc4 

例に移動したときに、それはそれぞれの製品番号を更新している、あなたがそれらの異なる製品番号の下に4箇所を見ることができるようです。

製品後で新しい場所にスキャン取得の上、それは場所1にあったように、それはまだ私の履歴データに残りますが、私の上記のクエリはそれをこの示し
---------------------------------------------------------- 
| Location 1 | Location 2 | Location 3 | Location 4 
---------------------------------------------------------- 
| 1234   |    |    |   |   
| 4567   |    |    |   | 
| 8978   |    |    |   | 
| 2578   |    |    |   | 
---------------------------------------------------------- 

---------------------------------------------------------- 
| Location 1 | Location 2 | Location 3 | Location 4 
---------------------------------------------------------- 
|    | 1234   |    |   |   
| 4567   |    |    |   | 
| 8978   |    |    |   | 
| 2578   |    |    |   | 
---------------------------------------------------------- 

それの取り出しを最終更新日に基づくデータ。 質問は私の上記のコードは長く見えます、特に私は将来的にさらに多くの場所を追加する予定です。 これを行うにはどんな良い方法ですか?

EDIT - サンプルデータ:私はあなたがノーノー一般的ではありません、あなたのSQLコード、内から書式設定の解決策を見つけるためにしようとしている印象を受けます

CREATE TABLE LocationsTest 
(
ProductNR varchar (14), 
Location int, 
Date Datetime, 

); 

Insert Into LocationsTest (ProductNR, Location, Date) 
Values('1234', 1, '2016-11-17 12:30:50.010'), 
     ('4567', 1, '2016-11-17 12:35:50.010'), 
     ('8978', 1, '2016-11-17 12:37:50.010'), 
     ('2578', 1, '2016-11-17 12:50:50.010'); 
+0

ソーステーブルとデータを入力するデータを入力してください。 – iamdave

+0

これは実際のテーブルではなく、私のデータベースとほぼ同じテーブルの例です。 データをアップロードできるサイトをご存知ですか?フィドルのような? – MishMish

+0

@MishMish製品がある場所から別の場所に移動したときは追跡しますか?製品が横断するすべての場所が維持されているテーブルがある場合、それは簡単なクエリになります。基本的に、履歴データが必要な場合は、それを追跡する必要があります。 –

答えて

0

。データ表示をプレゼンテーション層にどのように残すべきか。

それ以外のコードには、2つの例があります。まず、はどうすればがアプリケーション層にデータを返し、2番目が要求した形式になっているはずです。新しい場所がしかし含まれているとして、あなたはそれらを含めるようにPIVOTステートメントを更新し続ける必要があります:

CREATE TABLE LocationsTest 
(
ProductNR varchar (14), 
Location int, 
Date Datetime 

); 

Insert Into LocationsTest (ProductNR, Location, Date) 
Values('1234', 1, '2016-11-17 12:30:50.010'), 
     ('4567', 1, '2016-11-17 12:35:50.010'), 
     ('8978', 1, '2016-11-17 12:37:50.010'), 
     ('2578', 1, '2016-11-17 12:50:50.010'), 
     ('1234', 2, '2016-11-18 12:30:50.010'); -- I have added this row to simulate a Location move. 

-- This just drops out the relevant data for use in application level formatting: 
with mr 
as 
(
    select ProductNR 
      ,max(Date) as MostRecent 
    from LocationsTest 
    group by ProductNR 
) 
select l.ProductNr 
     ,l.Location 
from LocationsTest l 
    inner join mr 
     on l.ProductNR = mr.ProductNR 
      and l.Date = mr.MostRecent; 


-- This actually PIVOTs the data for you, but will need updating for every new location: 
with mr 
as 
(
    select ProductNR 
      ,max(Date) as MostRecent 
    from LocationsTest 
    group by ProductNR 
) 
select [1] as Location1 
     ,[2] as Location2 
     ,[3] as Location3 
     ,[4] as Location4 
from(
    select l.ProductNr 
      ,l.ProductNr as ProductNr2 -- This ensures all rows are returned in the PIVOT 
      ,l.Location 
    from LocationsTest l 
     inner join mr 
      on l.ProductNR = mr.ProductNR 
       and l.Date = mr.MostRecent 
) d 
pivot 
(max(ProductNr) for Location in([1],[2],[3],[4])) pvt 
; 
+0

こんにちはDave 答えは完璧です。あなたのコードを私の代わりに使うことをお勧めしますか? – MishMish

+0

@MishMish私はあなたの環境をテストしてそこから行くことができますが、あなたの複数の 'FULL OUTER JOIN'を実行すると思います。 – iamdave

+0

ありがとうございました:) – MishMish

1

私は実際には少しきれいかもしれないし、私が指摘したいの条件付き凝集の変化を示唆ニュアンスは、ProductNRMAX(date)の複数のレコードがある場合、iamdaveのレコードでMostRecentレコードを取得すると1つ以上の結果が生成されます。私はあなたのデータセットに他の人が投稿を読んでいる可能性は低いかもしれないことに気づきます。その理由のために私はROW_NUMBER()を使用してネクタイが必要な場合に希望のレコードを決定し、RANK()またはDENSE_RANK()を使用することをお勧めします。

あなたは私はあなたが単純化し、ちょうどこのような何かで行くことができると思うのつながりたくない場合は、次の

;WITH cteRowNums AS (
    SELECT DISTINCT 
     Location 
     ,ProductNR 
     ,RowNumber = RANK() OVER (PARTITION BY ProductNR ORDER BY Date DESC) 
    FROM 
     LocationsTest 
) 

SELECT 
    Location1 = MAX(CASE WHEN Location = 1 THEN ProductNR END) 
    ,Location2 = MAX(CASE WHEN Location = 2 THEN ProductNR END) 
    ,Location3 = MAX(CASE WHEN Location = 3 THEN ProductNR END) 
    ,Location4 = MAX(CASE WHEN Location = 4 THEN ProductNR END) 
FROM  
    cteRowNums 
WHERE 
    RowNumber = 1 
GROUP BY 
    ProductNR 
:あなたは次のようにそれだけで真の条件付き集約なっネクタイをしたいならば

;WITH cteRowNums AS (
    SELECT 
     Location 
     ,ProductNR 
     ,RowNumber = ROW_NUMBER() OVER (PARTITION BY ProductNR ORDER BY Date DESC) 
    FROM 
     LocationsTest 
) 

SELECT DISTINCT 
    Location1 = CASE WHEN Location = 1 THEN ProductNR END 
    ,Location2 = CASE WHEN Location = 2 THEN ProductNR END 
    ,Location3 = CASE WHEN Location = 3 THEN ProductNR END 
    ,Location4 = CASE WHEN Location = 4 THEN ProductNR END 
FROM  
    cteRowNums 
WHERE 
    RowNumber = 1 

その後、あなたは次のようにだけあなたが望むものを識別するためにROW_NUMBER()またはRANK()を使用するほとんど同じことを行うことができiamdaveのメソッドを使用するには:

;WITH cteRowNums AS (
    SELECT 
     Location = 'Location' + CAST(Location AS VARCHAR(10)) 
     ,ProductNR 
     ,RowNumber = ROW_NUMBER() OVER (PARTITION BY ProductNR ORDER BY Date DESC) 
    FROM 
     LocationsTest 
) 

, cteDesiredRecords AS (
    SELECT 
     Location 
     ,ProductNR 
     ,ProductNR2 = ProductNR 
    FROM  
     cteRowNums 
    WHERE 
     RowNumber = 1 
) 

SELECT * 
FROM 
    cteDesiredRecords 
    PIVOT (
     MAX(ProductNR) 
     FOR Location IN ([Location1],[Location2],[Location3],[Location4]) 
    ) p 

ボトムラインは、PIVOTはすばらしいコマンドですが、時には、あなたが望むことをするためにマッサージするために、あなたのレコードセットで少しの準備が必要です。そのような場合には、Conditional Aggregationを潜在的な代替手段と考えることができます。

+0

こんにちはマット、ありがとう、私もあなたの答えを与える:) – MishMish