我有以下三个SQL查询。我想将它们组合成一个是可能的,使用当前方法,或者如果它更有效则可以使用其他方法。
注意:我需要知道所有三个WHERE子句的不同计数值。
查询1:
SElECT COUNT(*) AS imgCount FROM (
SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images
UNION ALL
SELECT imgHeight, imgWidth, primaryId FROM secondary_images
) AS union_table
WHERE primaryId = $imgId AND imgWidth = $maxImageWidth AND imgHeight = $maxImageHeight;
QUERY 2:
SElECT COUNT(*) AS imgCount FROM (
SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images
UNION ALL
SELECT imgHeight, imgWidth, primaryId FROM secondary_images
) AS union_table
WHERE primaryId = $imgId AND imgWidth = $maxImageWidth AND imgHeight != $maxImageHeight;
QUERY 3:
SElECT COUNT(*) AS imgCount FROM (
SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images
UNION ALL
SELECT imgHeight, imgWidth, primaryId FROM secondary_images
) AS union_table
WHERE primaryId = $imgId AND imgWidth != $maxImageWidth AND imgHeight = $maxImageHeight;
另外,我的数据库是MySQL。我听说使用!=
表示“不相等”并不适用于所有情况,但<>
更好。在我的情况下,!=
应该没问题吗?
答案 0 :(得分:6)
这可能适合你。
SElECT COUNT(*) AS imgCount FROM (
SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images
UNION ALL
SELECT imgHeight, imgWidth, primaryId FROM secondary_images
) AS union_table
WHERE primaryId = $imgId
AND (imgWidth != $maxImageWidth AND imgHeight = $maxImageHeight
OR imgWidth = $maxImageWidth AND imgHeight != $maxImageHeight
OR imgWidth = $maxImageWidth AND imgHeight = $maxImageHeight);
我也相信这是等价的,虽然我不确定。
SElECT COUNT(*) AS imgCount FROM (
SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images
UNION ALL
SELECT imgHeight, imgWidth, primaryId FROM secondary_images
) AS union_table
WHERE primaryId = $imgId
AND (imgWidth = $maxImageWidth OR imgHeight = $maxImageHeight);
根据请求,这是一个返回3行的查询。
SELECT 'ALL EQUAL' AS COL1,COUNT(*) AS imgCount FROM (
SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images
UNION ALL
SELECT imgHeight, imgWidth, primaryId FROM secondary_images
) AS union_table
WHERE primaryId = $imgId AND imgWidth = $maxImageWidth AND imgHeight = $maxImageHeight
UNION ALL
SELECT 'WIDTH EQUAL' AS COL1,COUNT(*) AS imgCount FROM (
SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images
UNION ALL
SELECT imgHeight, imgWidth, primaryId FROM secondary_images
) AS union_table
WHERE primaryId = $imgId AND imgWidth = $maxImageWidth AND imgHeight != $maxImageHeight;
UNION ALL
SELECT 'HEIGHT EQUAL' AS COL1,COUNT(*) AS imgCount FROM (
SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images
UNION ALL
SELECT imgHeight, imgWidth, primaryId FROM secondary_images
) AS union_table
WHERE primaryId = $imgId AND imgWidth != $maxImageWidth AND imgHeight = $maxImageHeight;
答案 1 :(得分:2)
我认为需要CASE和GROUP BY:
SELECT CASE
WHEN imgWidth = $maxImageWidth AND imgHeight = $maxImageHeight
THEN 0
WHEN imgWidth != $maxImageWidth AND imgHeight = $maxImageHeight
THEN 1
WHEN imgWidth = $maxImageWidth AND imgHeight != $maxImageHeight
THEN 2
END AS count_type,
COUNT(*) AS imgCount
FROM (SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images
UNION ALL
SELECT imgHeight, imgWidth, primaryId FROM secondary_images
) AS union_table
WHERE primaryId = $imgId
AND (imgWidth = $maxImageWidth OR imgHeight = $maxImageHeight)
GROUP BY count_type;
至少很有诱惑力将WHERE子句压缩到UNION子查询中,但优化器无论如何都应该这样做。通过研究EXPLAIN输出来检查它是否确实这样做了。如果优化器没有自动执行谓词下推,您可以写:
SELECT CASE
WHEN imgWidth = $maxImageWidth AND imgHeight = $maxImageHeight
THEN 0
WHEN imgWidth != $maxImageWidth AND imgHeight = $maxImageHeight
THEN 1
WHEN imgWidth = $maxImageWidth AND imgHeight != $maxImageHeight
THEN 2
END AS count_type,
COUNT(*) AS imgCount
FROM (SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images
WHERE primaryId = $imgId -- or: imgId = $imgId
AND (imgWidth = $maxImageWidth OR imgHeight = $maxImageHeight)
UNION ALL
SELECT imgHeight, imgWidth, primaryId FROM secondary_images
WHERE primaryId = $imgId
AND (imgWidth = $maxImageWidth OR imgHeight = $maxImageHeight)
) AS union_table
GROUP BY count_type;
编写此解决方案的缺点是$maxImageWidth
和$maxImageHeight
变量每次使用4次(并且$imgId
一次)。如果您正在准备如图所示的语句(将值嵌入表示SQL的字符串中),那也不算太糟糕。如果您使用占位符,则需要为占位符指定一个命名方案(:img_ht
,:img_wd
,:img_id
(或至少:1
,:2
, :3
)代替?
占位符),因此您只能在EXECUTE语句中传递一次值。但是,该功能取决于您的DBMS; MySQL是许多不支持此功能的DBMS之一。
答案 2 :(得分:1)
您的primary_images和secondary_images表中是否有primaryId索引?如果是,那么你应该在里面推送where子句,以便可以使用索引。
SElECT COUNT(*) AS imgCount FROM (
SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images WHERE imgId = $imgId AND imgWidth != $maxImageWidth AND imgHeight = $maxImageHeight
UNION ALL
SELECT imgHeight, imgWidth, primaryId FROM secondary_images WHERE primaryId = $imgId AND imgWidth != $maxImageWidth AND imgHeight = $maxImageHeight
) AS union_table
否则将进行全表扫描以查找imgId,因为union_table是由Mysql创建的临时表,并且没有任何索引。