私は命令的に考えるので、私が望むものを関数型プログラミングに変換するのに苦労しています。基本的に、フォームの表と期待値の表があります。Expectation ビューでは、forms テーブルを調べて、それぞれが一致するかどうかを教えてくれるようにしたいと考えています。ただし、これを実現するために結合を使用しようとすると、2 つ以上のフォームが一致すると、結合によって Expectation テーブルに行が追加されます。これいらない。
命令的な方法で、私はこれと同等のものを求めています:
ForEach (row in Expectation table)
{
if (any form in the Form table matches the criteria)
{
MatchID = form.ID;
SignDate = form.SignDate;
...
}
}
私がSQLで持っているのはこれです:
SELECT
e.*, match.ID, match.SignDate, ...
FROM
POFDExpectation e LEFT OUTER JOIN
(SELECT MIN(ID) as MatchID, MIN(SignDate) as MatchSignDate,
COUNT(*) as MatchCount, ...
FROM Form f
GROUP BY (matching criteria columns)
) match
ON (form.[match criteria] = expectation.[match criteria])
これは正常に機能しますが、非常に遅く、2 つの一致があるたびに、Expectation の結果に行が追加されます。数学的には、結合がクロス乗算であり、これが予想されることを理解していますが、それらなしでこれを行う方法がわかりません。おそらくサブクエリ?
実装についてこれ以上詳しく説明することはできませんが、喜んで提案を試し、結果を返信します。880 の期待行があり、942 の結果が返されます。1 つのフォームに一致する結果のみを許可すると、831 件の結果が得られます。どちらも望ましいものではないので、あなたの回答が正確に 880 に到達した場合、あなたの回答が受け入れられます。
編集: SQL Server 2008 R2 を使用していますが、一般的なソリューションが最適です。
サンプルコード:
--DROP VIEW ExpectationView; DROP TABLE Forms; DROP TABLE Expectations;
--Create Tables and View
CREATE TABLE Forms (ID int IDENTITY(1,1) PRIMARY KEY, ReportYear int, Name varchar(100), Complete bit, SignDate datetime)
GO
CREATE TABLE Expectations (ID int IDENTITY(1,1) PRIMARY KEY, ReportYear int, Name varchar(100))
GO
CREATE VIEW ExpectationView AS select e.*, filed.MatchID, filed.SignDate, ISNULL(filed.FiledCount, 0) as FiledCount, ISNULL(name.NameCount, 0) as NameCount from Expectations e LEFT OUTER JOIN
(select MIN(ID) as MatchID, ReportYear, Name, Complete, Min(SignDate) as SignDate, COUNT(*) as FiledCount from Forms f GROUP BY ReportYear, Name, Complete) filed
on filed.ReportYear = e.ReportYear AND filed.Name like '%'+e.Name+'%' AND filed.Complete = 1 LEFT OUTER JOIN
(select MIN(ID) as MatchID, ReportYear, Name, COUNT(*) as NameCount from Forms f GROUP BY ReportYear, Name) name
on name.ReportYear = e.ReportYear AND name.Name like '%'+e.Name+'%'
GO
--Insert Text Data
INSERT INTO Forms (ReportYear, Name, Complete, SignDate)
SELECT 2011, 'Bob Smith', 1, '2012-03-01' UNION ALL
SELECT 2011, 'Bob Jones', 1, '2012-10-04' UNION ALL
SELECT 2011, 'Bob', 1, '2012-07-20'
GO
INSERT INTO Expectations (ReportYear, Name)
SELECT 2011, 'Bob'
GO
SELECT * FROM ExpectationView --Should only return 1 result, returns 9
'filed' はフォームを完了したことを示し、'name' はフォームを開始したが完了していない可能性があることを示します。私の見解には 4 つの異なる「一致基準」があります。それぞれがもう少し厳密で、それぞれをカウントします。'Name Only Matches'、'Loose Matches'、'Matches' (デフォルト)、'Tight Matches' (複数のデフォルト マッチがある場合に使用されます。