Изменить запрос SQL MAX, чтобы найти значение соответствующего поля - PullRequest
1 голос
/ 15 сентября 2011

У меня есть следующий запрос:

$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";

Это работает фантастически, но я хотел бы знать, как я могу найти значение столбца imgId, а такжеимя таблицы для значений maxWidth и maxHeight?

. Причина, по которой я этого хочу, заключается в том, что мне нужно знать, принадлежат ли значения maxWidth и maxHeight одному и тому же элементу в базе данных.

Мне интересно, возможно ли это путем изменения текущего запроса SQL?


Что было бы идеально, если бы, наряду с запросом значений maxWidth и maxHeight, логическое значение может быть настроено на вывод true, если оба maxWidth и maxHeight принадлежат одной и той же записи (хотя бы один раз).

Я думаю, поскольку данные изображения в primary_images является уникальным из данных в secondary_images (и наоборот), логическое значение может быть установлено в каждом из запросов, и пока существует один true, выводится true.Имеет ли это смысл?Это возможно?


Мне удалось собрать второй запрос, который использует значения maxWidth и maxHeight из первого запроса, чтобы вывести количество изображений в определенном наборе, которое содержитоба значения.Все, что меня действительно волнует, - это если равно или если не , то одно или несколько изображений, удовлетворяющих вышеуказанному требованию, так что, опять же, логическое значение будет лучше, чем общее число.Если у вас есть идея о том, как изменить следующее для отображения логического значения вместо количества результатов, дайте мне знать!

Меня заверили, что максимальное количество записей в обеих таблицах меньше 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 ]

3 голосов
/ 15 сентября 2011

[Оригинальный ответ ниже - это должно быть лучше]

Мне кажется, я неправильно понял ваш вопрос.Следующий запрос должен дать результирующий набор, который включает одну строку для каждого изображения, имеющего наибольшую высоту или наибольшую ширину по сравнению со всеми изображениями, и в нем будут указаны идентификатор и имя таблицы в строке вместе с высотой и шириной.

Поскольку максимальная высота и ширина могут не совпадать с одним и тем же изображением, в результате не обязательно может быть только одна строка с одним идентификатором изображения и источником таблицы.

Надеюсь, это как минимум ближек тому, что вы искали.

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 голос
/ 15 сентября 2011

Вы можете сделать это в двух запросах, возможно, легче читать таким образом. Первый запрос - это то, что вы должны получить, чтобы получить максимальную высоту и ширину.

Затем вы можете выполнить второй запрос, который выглядит следующим образом:

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] - это два значения, которые вы получаете из предыдущего запроса. Если они принадлежат одному и тому же идентификатору изображения, результат запроса будет больше нуля, в противном случае этот запрос не будет иметь результата.

Если вам нужно знать, какой идентификатор принадлежит какой таблице, вы можете создать искусственный столбец (например, источник), и ваш запрос будет выглядеть так:

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 4 из primary_images, а также primaryId 4,5 из secondary_images соответствует максимальной высоте и максимальной ширине предыдущего запроса

И, наконец, если вы просто хотите узнать, есть ли изображение, которое соответствует или нет, согласно нашим комментариям и обсуждению ниже, вы можете сделать:

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];

Где imgCount будет нулем, если нет подходящего изображения или больше нуля, в противном случае

1 голос
/ 15 сентября 2011

Вот что у меня так далеко. Это выглядит (и, вероятно, является) в значительной степени неоптимальным. Тем не менее, я публикую его в первую очередь, чтобы представить общую идею. Надеюсь, кто-то может разработать его, чтобы сделать результат более эффективным:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...