私はそれのようなものを返すクエリがあります:
Name Gender Job date of hire
John M mechanic 2012-05-08
John M electrician 2010-01-01
Vicky F scientific 2012-11-11
Bob M NULL NULL
各人の最初の仕事の名前、性別、仕事名が必要です。しかし、私は方法がわかりません。私のクエリは次のようになります:
select name,gender,jobname,hiredate
from person p
left join job j on p.personid = j.personid
Microsoft SQL Server 2000を使用しています
結果としてこれが必要です:
Name Gender Job
John M electrician
Vicky F scientific
Bob M NULL
あなたのデータは次のようになっていると思います:
個人テーブル
_╔══════════╦═══════╦════════╗
║ PersonID ║ Name ║ Gender ║
╠══════════╬═══════╬════════╣
║ 1 ║ John ║ M ║
║ 2 ║ Vicky ║ F ║
║ 3 ║ Bob ║ M ║
╚══════════╩═══════╩════════╝
_
ジョブテーブル
_╔══════════╦═════════════╦════════════╗
║ PersonID ║ JobName ║ HireDate ║
╠══════════╬═════════════╬════════════╣
║ 1 ║ Electrician ║ 2010-01-01 ║
║ 1 ║ Mechanic ║ 2012-05-08 ║
║ 2 ║ Scientific ║ 2012-11-11 ║
╚══════════╩═════════════╩════════════╝
_
最初のタスクは、各人の最初の仕事を(入社日で)見つけることです。これを行う1つのきちんとした方法は、相関サブクエリを使用することです。
_SELECT j.*
FROM dbo.Job AS j
WHERE
j.HireDate =
(
SELECT MIN(j2.HireDate)
FROM dbo.Job AS j2
WHERE j2.PersonID = j.PersonID
);
_
そこの内部クエリと外部クエリの間の相関_WHERE j2.PersonID = j.PersonID
_に注意してください。そのクエリの出力は次のとおりです。
_╔══════════╦═════════════╦════════════╗
║ PersonID ║ JobName ║ HireDate ║
╠══════════╬═════════════╬════════════╣
║ 1 ║ Electrician ║ 2010-01-01 ║
║ 2 ║ Scientific ║ 2012-11-11 ║
╚══════════╩═════════════╩════════════╝
_
実行計画(クラスター化された_PRIMARY KEY
_が_PersonID, HireDate
_である場合)は次のとおりです。
このプランの興味深い点は、元のクエリにJobテーブルへの参照が2つあるにもかかわらず、Jobテーブルが1回だけスキャンされることです。この計画では、私が Segment Top と呼ぶ最適化を使用しています。基本的に、実行エンジンはインデックスの順序を利用して新しいグループ(セグメント)の開始を検出し、各グループの最初の行だけを取得します(上)。
これで結果が得られたので、それをPersonテーブルに結合するだけです。
_SELECT
p.PersonName,
p.Gender,
j.JobName
FROM dbo.Person AS p
LEFT JOIN
(
-- Previous query
SELECT j.*
FROM dbo.Job AS j
WHERE
j.HireDate =
(
SELECT MIN(j2.HireDate)
FROM dbo.Job AS j2
WHERE j2.PersonID = j.PersonID
)
) AS j ON
j.PersonID = p.PersonID
OPTION (MERGE JOIN);
_
実行計画は次のとおりです。
OPTION (MERGE JOIN)
は必須ではありません。テーブルにこの小さな例よりも多くの行が含まれている場合に得られる可能性が高いプランを示すために追加しました。
テーブル定義とサンプルデータ:
_CREATE TABLE dbo.Person
(
PersonID integer NOT NULL,
PersonName varchar(30) NOT NULL,
Gender char(1) NOT NULL,
PRIMARY KEY (PersonID)
);
CREATE TABLE dbo.Job
(
PersonID integer NOT NULL,
JobName varchar(30) NOT NULL,
HireDate datetime NOT NULL,
PRIMARY KEY (PersonID, HireDate)
);
INSERT dbo.Person
(PersonID, PersonName, Gender)
SELECT 1, 'John', 'M' UNION ALL
SELECT 2, 'Vicky', 'F' UNION ALL
SELECT 3, 'Bob', 'M';
INSERT dbo.Job
(PersonID, JobName, HireDate)
SELECT 1, 'Mechanic', '20120508' UNION ALL
SELECT 1, 'Electrician', '20100101' UNION ALL
SELECT 2, 'Scientific', '20121111';
_
コメントのクエリを間違えました。グループでの性別を忘れました。このクエリは私にとってはうまくいきます:
select name,gender,SUBSTRING(job, 9, 50) as 'jobname'
from(
select name,gender,min(CONVERT(CHAR(8), hiredate, 112)+jobname) as'job'
from person p
left join job j on p.personid = j.personid
group by name,gender
) as query`