我是SQL新手,我想实现以下查询:
我有两张桌子,LicenseTblUnlockTbl
LicenseTbl包含有关购买的软件许可证的信息:
许可证ID、程序ID、所有者、位置、订单号、阻塞时间
UnlockTbl包含有关特定软件注册的信息:
UnlockID,LicenseID(进入LicenseTbl的外键),时间戳,序列号,密钥,卸载时间
其中BlockTime和UninstallTime包含一个时间戳(如果许可证被阻止或软件被卸载),否则为NULL
我想设计一个查询,为我提供以下条件适用的所有许可证持有人ID:
属于某个客户,
没有被阻止,
不是未在UnlockTbl中列出,就是行中有我写过这个,但我不确定它是否绝对正确(这是我第一次使用SQL查询):

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次的许可证。我更喜欢那些用得最少的,但不知道如何排序的。)

最佳答案

这是一个很好的开始,但我会将查询改为以下内容。。。

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
ALEFT JOIN确保返回LicenseTbl中的所有行,即使UnlockTbl表中没有匹配项。(如果没有匹配项,UnlockTbl表的值都表示为NULL
(第二章)。UnlockTbl.UninstallTime IS NULLJOIN而不是WHERE
WHERE子句在JOIN之后应用。这意味着UnlockTblUninstallTime具有实际值(非空)的任何记录都将被联接,然后被过滤掉。这反过来意味着,如果UnlockTbl中的所有相关记录在UninstallTime中都有非空值,则该许可证的所有行都将被筛选。
(第三章)。GROUP BY仅凭许可证,而不是钥匙。
简单地说,我不知道你为什么会把它放在那里,而且它也没有出现在你想要的东西的英文描述中。
由于您需要许可证ID列表,仅按该字段分组可确保为每个许可证ID获取一条记录。
(四)。HAVING修改子句以查看COUNT(DISTINCT SerialNo)
COUNT(*)统计所有记录。即使没有匹配(所有UnlockTbl值都显示为空),也会返回1
COUNT(SerialNo)仅统计SerialNo不为空的记录。如果没有匹配(所有UnlockTbl值都显示为空),则返回0
COUNT(DISTINCT SerialNo)也仅统计SerialNo不为空的记录,但将sme值的重复项仅视为1个条目。
5条)。ORDER BY COUNT(DISTINCT SerialNo)
获取与在HAVING子句中筛选的值相同的值,并按该值排序。

关于php - 我的JOIN + GROUP BY ... HAVING COUNT个查询正确吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10957111/

10-13 03:04