2016-10-28 40 views
2

MS SQLクエリが必要なヘルプ。データが最大と最小の間にある同じ列に、2つの値の差を表示する必要があります。最大値と最小値の間の同じ列の値の差はありますか?

see details behind the image

location| date  |amount 
------- | -------  |------- 
1000 | 2016-01-01 |400 
1000 | 2016-01-04 |600  
1000 | 2016-01-05 |650 
1000 | 2016-01-06 |820 
1000 | 2016-01-18 |850 
1000 | 2016-01-22 |900 
1000 | 2016-01-28 |910 
1000 | 2016-01-31 |950 
2000 | 2016-01-07 |100 
2000 | 2016-01-13 |150 
2000 | 2016-01-15 |260 
2000 | 2016-01-20 |330 

出力は次のようにする必要があります:事前に

location| difference 
------- | ------- 
1000 | 550 
2000 | 230 

おかげたとえば私は、次の表を持っている場合。

+2

HTTPです。 com/questions/285551 /なぜ私がアップロードできないのかをコードで確認するときの質問の画像/ 285557#28555 7 –

答えて

2

あなたはすることができ、以下のとおりです。

SELECT 
    location, 
    MAX(Amount) - MIN(Amount) difference 
FROM 
    Tbl 
GROUP BY 
    location 

SELECT 
    T.location, 
    Maxv.Amount - Minv.Amount as difference 
FROM 
(
    SELECT 
     location, 
     MIN(date) MinDate, 
     MAX(date) MaxDate 
    FROM 
     Tbl A 
    GROUP BY 
     location 
) T INNER JOIN 
Tbl Minv ON T.MinDate = Minv.date AND T.location = Minv.location INNER JOIN 
Tbl Maxv ON T.MaxDate= Maxv.date AND T.location = Maxv.location 
+0

ありがとうございました。より具体的には、最小額と最大金額ではなく、最小金額と最大金額の差額を探します。 – Jasu

+0

@Jasu回答が更新されました。 – NEER

+0

ご協力いただきありがとうございます。非常に便利です。 – Jasu

0
BEGIN TRAN 

CREATE TABLE #Details(_Location VARCHAR(100),_Date DATE,Amount INT) 
CREATE TABLE #Diff(Location VARCHAR(100),_MinDate DATE,_MaxDate DATE,Amount1 INT,Amount2 INT) 

INSERT INTO #Details(_Location ,_Date ,Amount) 
SELECT 1000,'2016-01-01',400 UNION ALL 
SELECT 1000,'2016-01-04',600 UNION ALL 
SELECT 1000,'2016-01-05',650 UNION ALL 
SELECT 1000,'2016-01-06',820 UNION ALL 
SELECT 1000,'2016-01-18',850 UNION ALL 
SELECT 1000,'2016-01-22',900 UNION ALL 
SELECT 1000,'2016-01-28',910 UNION ALL 
SELECT 1000,'2016-01-31',950 UNION ALL 
SELECT 2000,'2016-01-07',100 UNION ALL 
SELECT 2000,'2016-01-13',150 UNION ALL 
SELECT 2000,'2016-01-15',260 UNION ALL 
SELECT 2000,'2016-01-20',330 


INSERT INTO #Diff (Location ,_MinDate ,_MaxDate) 
SELECT _Location , MIN(_Date) _MinDate, MAX(_Date) _MaxDate 
FROM #Details 
GROUP BY _Location 


UPDATE #Diff SET Amount1 = Amount 
FROM #Details 
WHERE _Date = _MaxDate AND _Location = Location 

UPDATE #Diff SET Amount2 = Amount 
FROM #Details 
WHERE _Date = _MinDate AND _Location = Location 

SELECT Location , (Amount1 - Amount2) [Difference] 
FROM #Diff 

ROLLBACK TRAN 
+0

ありがとうございました。 – Jasu

0

を更新しましたこのお試しください:

簡単&ショート問合せ:

DECLARE @loc_tbl TABLE(location INT, loc_date DATE,amount INT) 
INSERT INTO @loc_tbl VALUES('1000','2016-01-01','400'), 
('1000','2016-01-04','600'),('1000','2016-01-05','650'), 
('1000','2016-01-06','820'),('1000','2016-01-18','850'), 
('1000','2016-01-22','900'),('1000','2016-01-28','910'), 
('1000','2016-01-31','950'),('2000','2016-01-07','100'), 
('2000','2016-01-13','150'),('2000','2016-01-15','260'), 
('2000','2016-01-20','330') 

SELECT A.location,(B.amount-C.amount) amt_difference FROM (SELECT location, 
MAX(loc_Date) maximum,MIN(loc_Date) minimum FROM @loc_tbl GROUP BY location) A 
LEFT JOIN @loc_tbl B ON B.loc_date = A.maximum 
LEFT JOIN @loc_tbl C ON C.loc_date = A.minimum 
+0

ありがとうございました。 – Jasu

+0

あなたの歓迎ですが、あなたのために働いていれば、それを正しいものとしてマークして、他の人が正しい答えを参照できるようにしてください。 :) @ジャス –

1

古典的なtop-n-per-groupの問題です。ここでは、topだけでなく、グループごとにbottomという値を取得する必要があります。

セルフジョインなしで達成するための標準的な方法の1つは、ROW_NUMBERです。あなたの場合、昇順と降順の2つの数字セットがあります。それが実行柱の仕組みを理解するには

サンプルデータ

DECLARE @T TABLE (location int, dt date, Amount int); 
INSERT INTO @T (location, dt, Amount) VALUES 
(1000,'2016-01-01',400), 
(1000,'2016-01-04',600), 
(1000,'2016-01-05',650), 
(1000,'2016-01-06',820), 
(1000,'2016-01-18',850), 
(1000,'2016-01-22',900), 
(1000,'2016-01-28',910), 
(1000,'2016-01-31',950), 
(2000,'2016-01-07',100), 
(2000,'2016-01-13',150), 
(2000,'2016-01-15',260), 
(2000,'2016-01-20',330); 

クエリ

WITH 
CTE 
AS 
(
    SELECT 
     location 
     ,dt 
     ,Amount 
     ,ROW_NUMBER() OVER (PARTITION BY location ORDER BY dt ASC) AS rnAsc 
     ,ROW_NUMBER() OVER (PARTITION BY location ORDER BY dt DESC) AS rnDesc 
    FROM @T 
) 
SELECT 
    location 
    ,SUM(CASE WHEN rnAsc = 1 THEN -Amount ELSE Amount END) AS diff 
FROM CTE 
WHERE 
    rnAsc = 1 
    OR rnDesc = 1 
GROUP BY location 
ORDER BY location; 

結果

+----------+------+ 
| location | diff | 
+----------+------+ 
|  1000 | 550 | 
|  2000 | 230 | 
+----------+------+ 

最初にCTE内でクエリを実行し、中間結果を調べます。

メインクエリは単にlocationでグループ化し、2つの値のSUMを計算します。 CASE式は、最初の値の符号を変更して差分を取得します。

1つの行だけの位置を持つことができる場合、結果は負の値Amountになります。あたかも0と唯一の利用可能なAmount値の間の差であるかのように。この場合、他の結果を得たい場合は、質問を明確にしてください。以下は

+0

おかげさまでありがとうございました。 – Jasu

0

表(名称:Myタブ)である://meta.stackoverflow以下

Location dt  amount 
    1000 2014-06-01 90 
    1000 2014-09-01 40 
    1000 2014-10-01 100 
    1000 2015-06-01 900 
    1000 2015-12-01 907 
    2000 2004-11-22 432 
    2000 2010-11-22 709 
    2000 2014-11-01 922 
    2000 2014-11-22 728 
    2000 2015-11-01 907 
    2000 2015-12-01 907 
    2000 2016-11-22 553 

クエリ

;WITH CTE 
AS(
SELECT location,min(dt) mindt,max(dt) maxdt from MyTab group by location 
) 
SELECT c.location,max(m.amount)-min(m.amount) amt from cte c 
INNER JOIN MyTab m on c.location = m.location and (c.mindt = m.dt or c.maxdt = m.dt) 
GROUP BY c.location 

出力は

location amt 
1000 817 
2000 121 
+0

ありがとうございました。 – Jasu

0
DECLARE @T TABLE (location int, dt date, Amount int); 
INSERT INTO @T (location, dt, Amount) VALUES 
(1000,'2016-01-01',400), 
(1000,'2016-01-04',600), 
(1000,'2016-01-05',650), 
(1000,'2016-01-06',820), 
(1000,'2016-01-18',850), 
(1000,'2016-01-22',900), 
(1000,'2016-01-28',910), 
(1000,'2016-01-31',950), 
(2000,'2016-01-07',100), 
(2000,'2016-01-13',150), 
(2000,'2016-01-15',260), 
(2000,'2016-01-20',540); 


with cte as (select location,first_value (amount)OVER(partition by location order by dt desc)v1 
,last_value(amount) OVER (partition by location order by (select NULL))as v2 
from @T 
) 
select distinct(location),v1-v2 from cte 
+0

ありがとうございました。 – Jasu

関連する問題