结合三个SQL查询

时间:2011-09-16 20:10:14

标签: mysql sql

我有以下三个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。我听说使用!=表示“不相等”并不适用于所有情况,但<>更好。在我的情况下,!=应该没问题吗?

3 个答案:

答案 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创建的临时表,并且没有任何索引。