我是SQL新手,我想实现以下查询:
我有两张桌子,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查询之一):
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次的许可证。我更喜欢那些已经使用过最少但却不知道如何排序的许可证。)
答案 0 :(得分: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
强>
LEFT JOIN
确保返回LicenseTbl
中的所有行,即使UnlockTbl
表中没有匹配项也是如此。 (如果没有匹配项,则UnlockTbl
表的值都表示为NULL
。)
<强> 2)。 UnlockTbl.UninstallTime IS NULL
中的JOIN
而不是WHERE
在<{em> WHERE
之后 这意味着JOIN
中UnlockTbl
具有实际值(NOT NULL)的任何记录都会加入,然后会被过滤掉。这反过来意味着如果 all UninstallTime
中的相关记录在UnlockTbl
中具有非NULL值,则该许可证的所有行都将被过滤。
第3)。只有许可证UninstallTime
,而不是密钥。
简单地说,我不知道你为什么会这样做,而且它没有出现在你想要的英文描述中。
如果您需要LicenseID列表,请按 分组该字段,以确保每个LicenseID获得一条记录。
<强> 4)。修改GROUP BY
子句以查看HAVING
COUNT(DISTINCT SerialNo)
统计所有记录。即使没有匹配(所有COUNT(*)
值显示为NULL),也会返回UnlockTbl
。
1
仅计算COUNT(SerialNo)
为非NULL的记录。如果没有匹配(所有SerialNo
值显示为NULL),则会返回UnlockTbl
。
0
也只计算COUNT(DISTINCT SerialNo)
为非NULL的记录,但将污点值的副本视为仅1个条目。
<强> 5)。 SerialNo
强>
取与ORDER BY COUNT(DISTINCT SerialNo)
子句中过滤的值相同,并按顺序排序。