我是SQL新手,我想实现以下查询:
我有两张桌子,LicenseTbl
和UnlockTbl
: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
A
LEFT JOIN
确保返回LicenseTbl
中的所有行,即使UnlockTbl
表中没有匹配项。(如果没有匹配项,UnlockTbl
表的值都表示为NULL
)(第二章)。
UnlockTbl.UninstallTime IS NULL
在JOIN
而不是WHERE
中WHERE
子句在JOIN
之后应用。这意味着UnlockTbl
中UninstallTime
具有实际值(非空)的任何记录都将被联接,然后被过滤掉。这反过来意味着,如果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/