2

特定の従業員、その人物の役割に必要なすべての「テスト」を返すクエリを作成しています。その人物はテストを受けていないか、テストの有効期限が切れています。

従業員ロールのすべてのテストをリストした最初の部分は次のとおりです。

SELECT e.EMP_NO, e.POS_CODE, p.PROPERTY_CODE, p.PROPERTY_VALUE
FROM COMPANY_PERS_ASSIGN e
INNER JOIN COMPANY_POS_PROPERTY_ALL p ON p.POS_CODE = e.POS_CODE
WHERE e.EMP_NO = '3615';

ここまでは順調です... この例では、この人物の役割に必要な 4 つのテストがリストされています。

次に、従業員が受けたテストを示すビューに結合する必要があります。

SELECT e.EMP_NO, e.POS_CODE, p.PROPERTY_CODE, p.PROPERTY_VALUE, ep.PROPERTY_CODE, ep.PROPERTY_VALUE
FROM COMPANY_PERS_ASSIGN e
INNER JOIN COMPANY_POS_PROPERTY_ALL p ON p.POS_CODE = e.POS_CODE
LEFT OUTER JOIN COMPANY_EMPLOYEE_PROPERTY_ALL ep ON ep.PROPERTY_VALUE = p.PROPERTY_VALUE
WHERE e.EMP_NO = '3615';

LEFT OUTER JOIN を使用すると、前のクエリからすべての行が返され、追加したばかりのビューから一致する情報があれば返されると思います。

このロールのテストが A/B/C/D で、この従業員がテスト A を 1 回、テスト D を 3 回行った場合、次の出力が期待されます。

3615 POS1 A A A A
3615 POS1 B B
3615 POS1 C C
3615 POS1 D D D D
3615 POS1 D D D D
3615 POS1 D D D D

しかし、代わりに私は得る:

3615 POS1 A A A A
3615 POS1 D D D D
3615 POS1 D D D D
3615 POS1 D D D D

私は PL/SQL よりも T-SQL に精通していますが、私が知る限り、正しいアプローチを取るべきでしたが、明らかに何かが正しくありません。

私は何が欠けていますか?

更新: ロジックに誤りがあることに気付きました。元のコード サンプルでは、​​COMPANY_EMPLOYEE_PROPERTY_ALL テーブルに結合し、PROPERTY_VALUE (つまりテスト) を介してリンクしましたが、従業員を考慮していませんでした。

これに対処する (そして別のことを試す) ために、サブクエリを導入しました。

SELECT e.EMP_NO, e.POS_CODE, p.PROPERTY_VALUE, p.value_description, ep.PROPERTY_VALUE, ep.value_description, ep.VALID_TO
FROM COMPANY_PERS_ASSIGN e
INNER JOIN COMPANY_POS_PROPERTY_ALL p ON p.POS_CODE = e.POS_CODE
LEFT OUTER JOIN 
    (Select ep.PROPERTY_VALUE, ep.VALID_TO, ep.value_description
    FROM COMPANY_PERS_ASSIGN e
    INNER JOIN COMPANY_EMPLOYEE_PROPERTY_ALL ep ON ep.EMP_NO = e.EMP_NO
    WHERE e.EMP_NO = '3615') ep on ep.PROPERTY_VALUE = p.PROPERTY_VALUE
WHERE e.EMP_NO = '3615'
AND (to_char(ep.VALID_TO) <= '17-APR-12' OR ep.VALID_To IS NULL);

このソリューションは機能します。

しかし、私が見つけた落とし穴を考えると、元のアプローチをどのように再調整できますか? または、このソリューションに固執する必要があります。私は「作業中」の段階ですが、常にさらなるエレガンス (および学習の機会) を探しています。

4

1 に答える 1

3

に関連する条件を左外部結合基準に追加してみてくださいEMP_NO:

SELECT e.EMP_NO, e.POS_CODE, p.PROPERTY_CODE, p.PROPERTY_VALUE, ep.PROPERTY_CODE, ep.PROPERTY_VALUE
FROM COMPANY_PERS_ASSIGN e
INNER JOIN COMPANY_POS_PROPERTY_ALL p ON p.POS_CODE = e.POS_CODE
LEFT OUTER JOIN COMPANY_EMPLOYEE_PROPERTY_ALL ep ON ep.PROPERTY_VALUE = p.PROPERTY_VALUE
                                                AND ep.EMP_NO = e.EMP_NO
WHERE e.EMP_NO = '3615'
-- AND (ep.VALID_TO <= to_date('20120417', 'yyyymmdd') OR ep.VALID_To IS NULL)
于 2012-04-17T15:08:47.687 に答える