我的JOIN + GROUP BY ... COUNT查询是否正确?

时间:2012-06-08 23:23:53

标签: php mysql sql count group-by

我是SQL新手,我想实现以下查询:

我有两张桌子,LicenseTblUnlockTbl

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

1 个答案:

答案 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之后 这意味着JOINUnlockTbl具有实际值(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)子句中过滤的值相同,并按顺序排序。