2009-04-21 19 views
2

あるテーブルからレコードを取得し、別のテーブルでその値が存在するかどうかを調べるためにクエリを行う必要があるデータベースがあります。そのテーブルは複数のレコードを返す可能性があり、最新の日付のレコードが必要です。SQL Server - テーブル参照でのクエリのパフォーマンス

ので、表1は、基本的には、次のとおりです。何のテストはSTUDENT_IDのために表2に存在しない場合、私は、私は、レコードをつもりのよう

ID (Primary Key) 
Name 
Test_Score 

そして、表2は

Test_Id (Primary) 
Student_ID (Foreign Key) 
Test_Score 
Test_Date 

です表1のスコアを使用したい場合は、表2のスコアを最新の日付で使用します。私はこれをC#コードで動作させていますが、クライアントはストアドプロシージャ内でそれをレポート目的で使用したいので、テーブルがかなり大きいのでパフォーマンスの問題が発生しています。また、この基本的な例は、実際には複数のテーブルに対して複数回発生します。

これを行うためのエレガントな方法があると確信していますが、高速で効率的ですが、カーソルを使用するだけでは何も出てこないようです。

誰かがストレートな解決法を知っていますか?

+0

を改善することに同意テーブルステートメントといくつかのダミーデータ) –

+0

少なくともテーブル名はいいと思いますが、あなたのdbスキーマはちょっとしたことで始まります。しかし、実際にはもっと知りません。 – Louis

答えて

3

ない100%構文の詳細についてはよく分からパーセントが、このような何か:それがどこにあるサブクエリが許可されていない場合

select table1.Name, ISNULL(table2.Test_Score, table1.Test_Score) 
from 
    table1 
    left outer join table2 
    on table1.id = table2.Student_ID 
    AND table2.Test_Date = (
     select max(x.Test_Date) 
     from table2 x 
     where table1.id = x.Student_ID 
     group by x.Student_ID) 

、WHERE句に移動します。 (申し訳ありませんが、今私はそれを試すことはできません)

Test_Dateが一意である場合のみクエリが機能します。そうでない場合は、繰り返しの結果が得られます。グループを使用する必要があります。

select table1.Name, min(ISNULL(table2.Test_Score, table1.Test_Score)) 
from 
    table1 
    left outer join table2 
    on table1.id = table2.Student_ID 
    AND table2.Test_Date = (
     select max(x.Test_Date) 
     from table2 x 
     where table1.id = x.Student_ID 
     group by x.Student_ID) 
group by table1.id, table1.Name 
+0

ありがとう、これは私が探していたものを探しています。今私はそこの最初の列から名前を得る方法を見つけなければなりません。 –

+1

これはシンプルです:-) –

2

Stefan Steineggerは基本的に正しい答えを持っています。

機能的分解を容易にする:各生徒に最新の日付の行を与えるビューを作成します。

次に、学生テーブル(あなたの質問のテーブル1)にそれを外部結合し、ビューに行がないテーブル1のテストスコアをとります。isnullまたはcoalesceを使用します。

1

Sql Server 2005を使用している場合、共通テーブル式(CTE)は優雅なソリューションを提供します。それぞれの生徒に最新のテストスコアを付けてCTEを作成し、生徒表に結合します。使用されているテストテーブルに結果が存在する場合、それ以外の場合はスチューデントテーブルのスコアが使用されます。

私はあなたのテーブルは、それぞれの学生とTestResultと呼ばれているものとし、またtest_idが、私はこのマシン上のコードをテストすることができないんだID

WITH RecentResults as (
    SELECT student_id, 
    test_score 
    FROM TestResult tr 
    WHERE tr.test_id = (SELECT MAX(test_id) FROM TestResult WHERE student_id = tr.student_id) 
) 
SELECT s.ID as 'Student ID', 
    isnull(rr.test_score, s.test_score) 
FROM Students s LEFT JOIN RecentResults rr ON s.ID = rr.student_id 

を増分自動であると仮定してきました - あなたが提供する場合DBスキーマの修正が容易になります。

+0

これは、max test_idが最新のテストであることを前提としています。... –

+0

合意 - 私はtest_idがauto inc IDであり、最新のものが最も高いIDです – Macros

1

ここに行く、SQL 2005のソリューションをテストし、ビューを回避することができますが、私は(作成その、簡単に私たちが解決策を記述するためのように、完全なサンプルコードを提供してください、それが明瞭

create table students (id int primary key, name nvarchar(50), score int) 
create table scores (test_id int, student_id int, score int, date datetime) 

insert students values (1, 'bob', 1) 
insert students values (2,'bill', 55) 
insert scores values (22,1,88,getdate()) 
insert scores values (23,1,88,getdate() + 1) 
insert scores values (23,1,89,getdate() + 2) 

go 

create view latest_scores 
as 
select scores.student_id, scores.date, score 
from scores 
join 
(
    select student_id, date = max(date) from scores 
    group by student_id 
) maxDates on maxDates.student_id = scores.student_id and maxDates.date = scores.date 

go 

select Id, isnull(l.score, s.score) from students s 
left join latest_scores l on student_id = id 
+0

これは、日付に時間要素があることを前提にしているか、学生が1日に1回以上のテストを受けていないことを前提としています; – Macros

+0

真実は、 –

関連する問題