5

ですから、SQL は開発者としての私の最も弱い面だと言わざるを得ません。おそらく、私が達成しようとしていることはかなり簡単です。私はこのようなものを持っています (これは実際のモデルではありませんが、説明に時間を浪費することなく理解しやすくするために、使用する必要があるテーブルの関係を正確に模倣する例を​​考え出しました)。一方では、テーブルを「ユーザー」と呼びましょう。主キー「UserId」、「UserName」などの列。

次に、別の表「ライセンス」です。ユーザーと 1:N で関連付けます。各ライセンスは 1 人のユーザーに属し、ユーザーは複数のライセンスを持つことができます。したがって、PK IdLicense、FK IdUser などがあります。

続いて「Equipments」というテーブル。ここでは、さまざまな機器を定義しています。IdEquipment、EquipmentName. それについては、これ以上言うことはありません。

最後に、「ライセンス」と「機器」の間の N:M 関係を作成するテーブル。ユーザーは、ライセンスを定義するときに、ライセンスで操作できるさまざまな機器を指定できます。したがって、ライセンスは複数の機器に関連付けることができ、機器の一部は複数のライセンスに関連付けることができます。

本当の取引はここに来ます。装備の取り扱い資格をもとにユーザーを絞り込める何らかの検索システムの実装を命じられた。 "、"B"、"C"。たとえば、James と Dave の 2 人のユーザーがいるとします。James には 2 つのライセンスがあり、Dave には 1 つのライセンスがあります。James は、最初のライセンスでマシン "A" と "D" を使用する資格があり、2 番目のライセンスで "B" と "C" を使用する資格があります。Dave は、彼の唯一のライセンスで、機器タイプ "B" および "C" を処理する資格があります。機器「A」、「B」、および「C」を処理できるユーザーを誰かが検索しようとすると、返されるレコードは James だけになります。

これまでのところ、次のようなことをしなければならないと思っていました

SELECT DISTINCT IdUser
FROM  Users
INNER JOIN Licenses
   ON Licenses.IdUser = Users.idUser
INNER JOIN LicensesEquipments
   ON LicensesEquipments.IdLicense = Licenses.IdLicense
INNER JOIN Equipment
   ON Equipment.IdEquipment = LicensesEquipments.IdEquipment

WHERE Equipment.IdEquipment = ??

「A」「B」および「C」の 3 つの異なる idEquipments すべてでこれをフィルタリングするにはどうすればよいですか? 明らかに、セルが 2 つの異なる値に等しくならないため、WHERE Equipment.IdEquipment = 1 と Equipment.IdEquipment = 2 を作成することはできません。WHERE Equipment.IdEquipment = 1 または Equipment.IdEquipment = 2 も実行できません。OR を使用すると、可能性の少なくとも 1 つを保持しているユーザーが有効な結果と見なされるため、3 つすべてを持つユーザーを探しています。この場合のさまざまな機器。

最初は、エイリアスを使用して、テーブル機器で複数の内部結合を作成し、機器のフィルターと同じ回数それを行い、各エイリアスを異なるフィルターで使用する必要があると想定しました。しかし、その後、私のコードスーパーバイザーがやって来て、それを忘れるように言いました。なぜなら、彼は、フィルターを追加するとコストがかかりすぎると言ったからです (ただし、彼はより良い代替手段を提供しませんでした...)

4

2 に答える 2

4
SELECT Users.idUser
FROM Users
INNER JOIN Licenses ON Licenses.IdUser = Users.idUser
INNER JOIN LicensesEquipments ON LicensesEquipments.IdLicense = Licenses.IdLicense
INNER JOIN Equipment ON Equipment.IdEquipment = LicensesEquipments.IdEquipment
WHERE Equipment.IdEquipment IN ('A', 'B', 'C')
GROUP BY IdUser
HAVING COUNT(DISTINCT Equipment.IdEquipment) = 3 <--must be # of unique items in IN clause

本当にユーザー ID だけが必要な場合は、クエリからUsersおよびLicensesテーブルを削除できます。

SELECT Licenses.IdUser
FROM Licenses 
INNER JOIN LicensesEquipments ON LicensesEquipments.IdLicense = Licenses.IdLicense
WHERE LicensesEquipments.IdEquipment in ('A', 'B', 'C')
GROUP BY Licenses.IdUser
HAVING COUNT(DISTINCT LicensesEquipments.IdEquipment) = 3

また、いくつかのエイリアスを使用すると読みやすくなります。

SELECT l.IdUser
FROM Licenses l
INNER JOIN LicensesEquipments le ON le.IdLicense = l.IdLicense
WHERE le.IdEquipment in ('A', 'B', 'C')
GROUP BY l.IdUser
HAVING COUNT(DISTINCT le.IdEquipment) = 3
于 2012-10-31T01:11:10.193 に答える
0
SELECT l.IdUser
FROM Licenses l
INNER JOIN LicensesEquipments le ON le.IdLicense = l.IdLicense
WHERE le.IdEquipment in (`enter code here`'A', 'B', 'C')
GROUP BY l.IdUser
HAVING COUNT(DISTINCT le.IdEquipment) = 3
于 2013-11-14T09:05:22.317 に答える