1

私はSQLを初めて使用し、次のクエリを実装したいと考えています。

私は2つのテーブルを持っています、LicenseTblそしてUnlockTbl

LicenseTbl購入したソフトウェアライセンスに関する情報が含まれています。

LicenseID、ProgramID、Owner、Location、OrderNo、BlockTime

UnlockTbl特定のソフトウェア登録に関する情報が含まれています。

UnlockID、LicenseID(LicenseTblへの外部キー)、Timestamp、SerialNo、Key、UninstallTime

ここで、BlockTimeとUninstallTimeには、ライセンスがブロックされた場合、またはソフトウェアがアンインストールされた場合などにタイムスタンプが含まれNULLます。

次の条件が当てはまるすべてのLicenseIDを取得するクエリを考案したいと思います。

  • 特定の顧客に属し、
  • ブロックされていません、
  • UnlockTblにリストされていないか、アンインストール済みとしてマークされていない行にX個未満の異なるSerialNoがあります。

私はこれを書きましたが、それが絶対的に正しいかどうかはわかりません(これは私の最初のSQLクエリの1つです):

SELECT LicenseID FROM LicenseTbl
JOIN UnlockTbl
   ON (LicenseTbl.LicenseID = UnlockTbl.LicenseID) 
WHERE  LicenseTbl.OrderNo   = '$givenOrderNo'
   AND LicenseTbl.Owner     = '$givenOwner'
   AND LicenseTbl.Location  = '$givenLocation'
   AND LicenseTbl.BlockTime IS NULL
   AND UnlockTbl.UninstallTime IS NULL
GROUP BY LicenseTbl.LicenseID, UnlockTbl.Key
HAVING COUNT(*) < $X

(つまり、同時に使用された回数がX回未満のすべてのライセンスを一覧表示します。最初に使用された回数が最も少ないライセンスを優先しますが、そのように並べ替える方法がわかりません。)

4

1 に答える 1

4

これは良いスタートですが、クエリを次のように変更します...

SELECT
  LicenseID
FROM
  LicenseTbl
LEFT JOIN
  UnlockTbl
    ON  UnlockTbl.LicenseID = LicenseTbl.LicenseID
    AND UnlockTbl.UninstallTime IS NULL
WHERE
      LicenseTbl.OrderNo   = '$givenOrderNo'
  AND LicenseTbl.Owner     = '$givenOwner'
  AND LicenseTbl.Location  = '$givenLocation'
  AND LicenseTbl.BlockTime IS NULL
GROUP BY
  LicenseTbl.LicenseID
HAVING
  COUNT(DISTINCT UnlockTbl.SerialNo) < $X
ORDER BY
  COUNT(DISTINCT UnlockTbl.SerialNo)

1)。LEFT JOIN

Aは、テーブルに一致するものがない場合でも、LEFT JOINのすべての行が返されることを保証します。 (一致するものがない場合、テーブルの値はすべてとして表されます。)LicenseTblUnlockTblUnlockTblNULL

2)。UnlockTbl.UninstallTime IS NULLでではJOINなくWHERE

このWHERE句は、のに適用されJOINます。これは、実際の値(NOT NULL)UnlockTblを持つすべてのレコードが結合されてからフィルターで除外されることを意味します。これは、のすべての関連レコードのがNULL以外の値である場合、そのライセンスのすべての行がフィルタリングされることを意味します。UninstallTimeUnlockTblUninstallTime

3)。GROUP BYキーではなく、ライセンスのみで。

簡単に言えば、なぜあなたがそこにそれを持っていたのか分かりません、そしてそれはあなたが望むものの英語の説明には現れません。

LicenseIDのリストが必要な場合は、そのフィールドのみでグループ化すると、LicenseIDごとに1つのレコードを取得できます。

4)。HAVING見るように変更された句COUNT(DISTINCT SerialNo)

COUNT(*)すべてのレコードをカウントします。一致するものがなかった場合でも(すべてのUnlockTbl値がNULLとして表示されます)、これはを返し1ます。

COUNT(SerialNo)NOTNULLのレコードのみをカウントしSerialNoます。一致するものがなかった場合(すべてのUnlockTbl値がNULLとして表示されます)、これはを返し0ます。

COUNT(DISTINCT SerialNo)また、がNULLでないレコードのみをカウントしSerialNoますが、sme値の重複は1つのエントリとして扱います。

5)。ORDER BY COUNT(DISTINCT SerialNo)

HAVING句でフィルタリングされているのと同じ値を取り、それによって順序付けます。

于 2012-06-08T23:51:53.507 に答える