修改SQL MAX查询以查找对应字段的值

时间:2011-09-15 04:40:45

标签: mysql sql

我有以下问题:

$imgDimensions_query = "SELECT MAX(imgWidth) maxWidth, MAX(imgHeight) maxHeight FROM (
    SELECT imgHeight, imgWidth FROM primary_images WHERE imgId=$imgId
    UNION 
    SELECT imgHeight, imgWidth FROM secondary_images WHERE primaryId=$imgId) as MaxHeight";

它工作得很棒,但我想知道如何为imgIdmaxWidth值找到maxHeight列的值以及表名称?

我想要这个的原因是我需要知道maxWidthmaxHeight值是否属于数据库中的同一项。

我想知道通过修改当前的SQL查询是否可以做到这一点?


如果同时查询maxWidthmaxHeight值,如果同时true和{maxWidth,则可以将布尔值设置为输出maxHeight。 {1}}属于同一条目(至少一次)。

我在想,因为primary_images中的图像数据与secondary_images中的数据是唯一的(反之亦然),所以可以在每个查询中设置布尔值,并且如果存在一个true,则输出true。那有意义吗?这可能吗?


我设法将第二个查询放在一起,该查询使用第一个查询中的maxWidthmaxHeight的值来输出包含两个值的特定集合中的图像数量。所有我真正关心的是,如果或者不是一个或多个符合上述要求的图像,那么布尔值将比总数更好数。如果你知道如何修改以下内容以显示布尔值而不是结果数,请告诉我!

我已经确信,如果两个表中的最大条目数小于1000,则使用两个查询而不是一个查询不应该导致命中速度。如果您也这么认为,如果将这些查询合并为一个是荒谬的,那么请告诉我。

第二个问题:

$haveDimensions_query = "SELECT sum(rows) AS total_rows FROM (
    SELECT count(*) AS rows FROM primary_images WHERE imgId = $imgId and imgWidth = $maxImageWidth and imgHeight = $maxImageHeight
    UNION ALL
    SELECT count(*) AS rows FROM secondary_images WHERE primaryId = $imgId and imgWidth = $maxImageWidth and imgHeight = $maxImageHeight
) as union_table";

3 个答案:

答案 0 :(得分:3)

[原始答案如下 - 这应该更好]

我想我误解了你的问题。以下查询应该为每个图像提供一个结果集,其中包含与所有图像相比具有最大高度或最大宽度的每个图像,并且行中将包含ID和表名以及高度和宽度。

由于最大高度和宽度可能不是来自同一图像,因此结果中不一定只有一行具有单个图像ID和表源。

我希望这至少比你想要的更接近。

SELECT
  imgId,
  tName,
  imgWidth,
  imgHeight
FROM (
        SELECT imgId, 'Primary' tName, imgHeight, imgWidth
        FROM primary_images WHERE imgId=$imgId
        UNION 
        SELECT imgId, 'Secondary' tName, imgHeight, imgWidth
        FROM secondary_images WHERE primaryId=$imgId
      ) as T
WHERE 
 (T.imgHeight >= (SELECT MAX(imgHeight) FROM primary_images)
  AND
  T.imgHeight >= (SELECT MAX(imgHeight) FROM secondary_images)
 )
 OR
 (T.imgWidth >= (SELECT MAX(imgWidth) FROM primary_images)
  AND
  T.imgWidth >= (SELECT MAX(imgWidth) FROM secondary_images)
 )

- 以下的原始答案 -

尝试这样的事情:

   SELECT
      imgId,
      tName,
      MAX(imgWidth) maxWidth,
      MAX(imgHeight) maxHeight FROM (
        SELECT imgId, 'Primary' tName, imgHeight, imgWidth
        FROM primary_images WHERE imgId=$imgId
        UNION 
        SELECT imgId, 'Secondary' tName, imgHeight, imgWidth
        FROM secondary_images WHERE primaryId=$imgId
      ) as T
   GROUP BY imgId, tName;

(MaxHeight不是派生表的好名称,因为它不是最大高度的表。我将其更改为T.)

答案 1 :(得分:1)

这是我到目前为止所得到的。它看起来(并且可能是)非常不理想。尽管如此,我发布它主要是为了介绍一般的想法。希望有人可以开发它以使结果更有效:

SELECT
  m.maxWidth,
  m.maxHeight,
  (u.imgWidth IS NOT NULL) AS OneImageHasBoth
FROM (
  SELECT
    MAX(imgWidth)  AS maxWidth,
    MAX(imgHeight) AS maxHeight
  FROM (
    SELECT imgWidth, imgHeight
    FROM primary_images
    UNION
    SELECT imgWidth, imgHeight
    FROM secondary_images
  ) u
) m
  LEFT JOIN  (
    SELECT imgWidth, imgHeight
    FROM primary_images
    UNION
    SELECT imgWidth, imgHeight
    FROM secondary_images
  ) u ON m.maxWidth = u.imgWidth AND m.maxHeight = u.imgHeight

显然,优化这种方法的一种方法是将重复联合的结果存储到临时表中。我不确定您的特定环境是否允许您发出多语句查询,但如果确实如此,那肯定会有助于加快查询速度。

你想要分别找到每个表的结果然后合并它们的想法实际上并不坏。但我认为结合结果背后的逻辑应该更复杂一些。一个明显的例子是,一个表的结果包含true而另一个表false,但后者具有更大的宽度和高度,因此返回true将是不正确的。或者考虑这个例子:

假设primary_images的结果是

maxWidth  maxHeight  OneImageHasBoth
--------  ---------  ---------------
1152      864        true

secondary_images它的

maxWidth  maxHeight  OneImageHasBoth
--------  ---------  ---------------
1280      800        true

两个表都包含两个属性最大的图像,但很明显,如果查询已应用于联合集,OneImageHasBoth将为false

因此,正如您所看到的,将两个结果组合起来应该比仅依靠其中一个true的存在更为复杂。

我尝试实施该方法:

SELECT
  CASE WHEN p.maxWidth  > s.maxWidth  THEN p.maxWidth  ELSE s.maxWidth  END AS maxWidth,
  CASE WHEN p.maxHeight > s.maxHeight THEN p.maxHeight ELSE s.maxHeight END AS maxHeight,
  (
    p.maxWidth >= s.maxWidth AND p.maxHeight >= s.maxHeight AND p.OneImageHasBoth OR
    p.maxWidth <= s.maxWidth AND p.maxHeight <= s.maxHeight AND s.OneImageHasBoth
  ) AS OneImageHasBoth
FROM (
  SELECT DISTINCT
    m.maxWidth,  m.maxHeight,
    (i.imgWidth IS NOT NULL) AS OneImageHasBoth
  FROM (
    SELECT
      MAX(imgWidth)  AS maxWidth,
      MAX(imgHeight) AS maxHeight
    FROM primary_images
  ) m
    LEFT JOIN primary_images i ON m.maxWidth = i.imgWidth AND m.maxHeight = i.imgHeight
) p
CROSS JOIN (
  SELECT DISTINCT
    m.maxWidth,  m.maxHeight,
    (i.imgWidth IS NOT NULL) AS OneImageHasBoth
  FROM (
    SELECT
      MAX(imgWidth)  AS maxWidth,
      MAX(imgHeight) AS maxHeight
    FROM secondary_images
  ) m
    LEFT JOIN secondary_images i ON m.maxWidth = i.imgWidth AND m.maxHeight = i.imgHeight
) s

答案 2 :(得分:1)

你可以在两个查询中执行此操作,这可能更容易阅读。 第一个查询是获得最大高度和宽度所需要的。

然后,您可以发出第二个查询,如下所示:

SElECT primaryId FROM (
   SELECT imgHeight, imgWidth, imgId AS primaryId FROM primary_images
    UNION 
    SELECT imgHeight, imgWidth, primaryId FROM secondary_images
) as union_table
WHERE imgWidth = [maxWidth] and imgHeight = [maxHeight];

[maxWidth][maxHeight]是您从上一个查询中获得的两个值。如果它们属于同一个图像ID,则查询结果大于零,否则此查询将没有结果。

如果您需要知道哪个ID属于哪个表,您可以创建人工列(例如来源),您的查询将变为:

SElECT primaryId, source FROM (
   SELECT imgHeight, imgWidth, imgId AS primaryId, 1 as source FROM primary_images
    UNION 
    SELECT imgHeight, imgWidth, primaryId, 2 as source FROM secondary_images
) as union_table
WHERE imgWidth = [maxWidth] and imgHeight = [maxHeight];

请注意,现在有一个名为source的人工列。因此,如果您的查询结果是

primaryId     source
4             1 
4             2
5             2

您知道来自imgId的{​​{1}} 4以及primary_images 4 来自primaryId的{​​{1}} 4,5与上一个查询的最大高度和最大宽度相匹配

最后,如果你只是想知道是否有匹配的图像,根据我们下面的评论和讨论,你可以这样做:

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 = [maxWidth] and imgHeight = [maxHeight];

如果没有匹配的图像,secondary_images将为零,否则为