2017-11-17 5 views
1

私の同僚によると、私たちはIBM DB2を使用していますSQL別個のIDごとに複数の代わりに1行を返すにはどうすればよいですか?

IDごとにSQLを1行戻すのに本当に苦労しています。仕事で周りに尋ねられたが、ここで女の子はSQLといいです...私はいくつかのSQLを行うことはできますが、SQLの専門家はいません。

良いことを説明するために、私はここで

下の例を設定するにはテーブルとそのデータ

ID DATE  CODE PERCENT 
01 2016-08-21 1111 52 
01 2016-09-06 1111 60 
01 2016-10-06 1112 38 
02 2016-05-01 6666 50 
02 2016-10-01 1111 50 

である私は1つのレコードが最も早い日付で、各IDごとに返さたいです。 だから私はSQL

SELECT ID, MIN(DATE) 
FROM TABLE 
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01' 
AND CODE = 1111 
GROUP BY ID 

これはうまくいきました。私は得るだろう

01 2016-08-21 
02 2016-10-01 

私はすぐにもPERCENT列が必要であることを知った。

SELECT ID, MIN(DATE), PERCENT 
FROM TABLE 
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01' 
AND CODE = 1111 
GROUP BY ID, PERCENT 

が、今、私が間違っているID 01のための複数の行を取得しています...

01 2016-08-21 1111 52 
01 2016-09-06 1111 60 
02 2016-10-01 1111 50 

は、誰かが私はこのSQLを修正するか、右方向に私を指す助けることができるようにI以下のようにIDごとに1行を持つことができますか?

01 2016-08-21 1111 52 
02 2016-10-01 1111 50 
+0

これはMS SQL Serverですか? – Sarhang

+1

どのdbms ?????????? SQLはちょうどlanguです年齢。実装はdbmsごとに異なります。 – Eric

+0

Alisonでは、使用するデータベースの種類(MySQL Oracle、Postgres、SQL Serverなど)を知ることは非常に重要です。なぜなら、ソリューションはデータベースがサポートしているものに依存するからです。 「SQL」はそれだけでは詳細が十分ではありません。 –

答えて

0
SELECT 
    Earliest.ID, 
    Earliest.Date, 
    TABLE.PERCENT 
FROM (
    SELECT 
     ID, 
     MIN(DATE) 
    FROM 
     TABLE 
    WHERE 
     DATE BETWEEN '2016-01-01' AND '2017-11-01' 
     AND CODE = 1111 
    GROUP BY ID 
) AS Earliest 
INNER JOIN TABLE ON Earliest.ID = Table.ID 

あなたの調整クエリが複数のレコードを返している理由を説明する:パーセント列が異なるデータを持っており、そのときのグループそれによって、その上のすべての変更のための新しいレコードを追加します。

この回答では、要約された結果に参加することで、基礎となるテーブルのパーセントを取得します。

1

GROUP BY IDは必要な処理を行います。GROUP BYパーセントは必要ありません。 GROUP BYの値が異なるため、新しい行が追加されます。

SELECT ID, MIN(DATE), code, percent 
FROM table 
WHERE DATE BETWEEN '2016-01-01' AND '2017-11-01' 
AND CODE = 1111 
GROUP BY ID; 

これが役に立ちます。

+0

ほとんどのdbmsが壊れます。 – Eric

0

これは、SQL Serverの場合は、ORDER BYと一緒にTOP 1 WITH TIESを使用することができます。

SELECT TOP 1 WITH TIES ID, DATE, PERCENT 
FROM TABLE 
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01' 
AND CODE = 1111 
ORDER BY ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DATE ASC) 
0

はないパーセントグループ、ちょうどグループIDによってを行います。 selectステートメントにコードを追加します。

select id, min(date), code, percent 
from tablename 
where date between '2016-01-01' AND '2017-11-01' 
and code = 1111 
group by id; 
+0

このコードはANSI SQLに準拠していませんが、Sybase ASEおよびおそらくMySQLで実行されます。彼らはgroup by節なしでselectを受け入れます。 – ColdCat

0

私はあなたがMS SQL Serverを使用していると仮定します。あなたは分の日付を取得するには、(cluse付き)CTEとして知られているものを使用し、メインテーブルにそれを参加することができます:see the working example on sql fiddle

-- first find the min date for each ID 
with min_date as (
SELECT ID, MIN(DATE) [DATE] 
FROM tbl 
WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01' 
AND CODE = 1111 
GROUP BY ID 
) 

-- join it to the table and get the result 
select t.ID, md.[DATE], t.[PERCENT] 
from tbl t 
inner join min_date as md 
on md.ID = t.ID and md.[DATE] = t.[date] 
1

あなたデータベースはrow_number() over()をサポート場合は、その機能を使用すると、優れた方法でありますその決定の行があり、このような「最古」:

select * 
from (
     select * 
      , row_number() over(partition by ID, CODE order by DATE ASC) as is_oldest 
     from YOURTABLE 
     where DATE >= '2016-01-01' AND DATE <= '2017-11-01' 
     and CODE = 1111 
    ) d 
where is_oldest = 1 

本の重要な利点は、それが参加しなくても、「最も古い」に関連付けられた行全体へのアクセスを提供します。

このアプローチの柔軟性にも注意してください。

select * 
from (
     select * 
      , row_number() over(partition by ID, CODE order by date ASC) as is_oldest 
      , row_number() over(partition by ID, CODE order by date DESC) as is_recent 
     from your_table 
     WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01' 
     AND CODE = 1111 
    ) d 
where is_oldest = 1 
or is_recent = 1 

「最新のもの」を得るには、ASCendingからDESCendingへの順序を変更するだけです。

NB:V8へのMySQLの前には、ROW_NUMBERとして「ウィンドウ関数をサポートしていませんが、それは以降のV8で計画されている他の多くのデータベースは、この機能をサポートしてPERCENTためであることにより、

0

理由パーセントがグループを破ります。列の間に異なっており、あなたが持つ削除重複あるGROUP BY。PERCENTは、あなたが代わりに同じIDとMIN(DATE)

SELECT dT.ID 
     ,dT.DATE 
     ,(SELECT T.PERCENT 
      FROM TABLE T 
     WHERE T.ID = dT.ID AND T.DATE = dT.DATE 
     ) AS Percent 
    FROM (
     SELECT ID, MIN(DATE) AS DATE 
      FROM TABLE 
      WHERE DATE >= '2016-01-01' AND DATE <= '2017-11-01' 
      AND CODE = 1111 
     GROUP BY ID 
     ) AS dT 
を持つテーブルから行を再取得する副問合せすることができます...行が違います
関連する問題