Получить одну строку от 1 до нескольких отношений между тремя таблицами - PullRequest
1 голос
/ 19 июля 2010

У меня есть следующие три таблицы:

---- ---- ПРОДУКТ

PRODUCT_ID     DESC     
1              'Pencil'   
2              'Paper'

---- PRICE_BY_SUPPLIER ----

PRODUCT_ID     SUPPLIER_ID     PRICE  
1              1               10  
1              2               9  
1              3               9.5  
2              1               5

---- IMAGES_BY_PRODUCT ----

PRODUCT_ID     NAME  
1              'pencil.img'  
1              'pen.img'  
1              'pencil_other.img'  
2              'paper.img'

Я бы хотел запрос с минимальной ценой, подсчетом поставщика, у которого есть товар, и одним изображением (одно изображение среди всех поставщиков). Выходной запрос должен выглядеть следующим образом:

---- FINAL_QUERY ----

PRODUCT_ID     MIN_PRICE     IMAGE          SUPPLIER_COUNT  
1              9             'pencil.img'   3  
2              5             'paper.img'    1

У меня есть этот запрос, который возвращает все, кроме изображения.

SELECT f.PRODUCT_ID, f.DESC, x.MIN_PRICE, x.SUPPLIER_COUNT  
  FROM (
        SELECT pp.PRODUCT_ID, 
               MIN(pp.PRICE) AS MIN_PRICE, 
               COUNT(pp.PRODUCT_ID) AS SUPPLIER_COUNT 
          FROM PRICE_BY_SUPPLIER AS pp 
         GROUP 
            BY pp.PRODUCT_ID
       )   
       AS x
       INNER JOIN PRODUCT AS f 
         ON f.PRODUCT_ID = X.PRODUCT_ID

Можете ли вы помочь мне завершить мой запрос?

Ответы [ 3 ]

0 голосов
/ 19 июля 2010

Попробуйте это:

SELECT DISTINCT p.product_id, MIN(pbs.price), ibp.name, pbs.supplier_id
FROM product p
INNER JOIN price_by_supplier pbs
ON  p.product_id = pbs.product_id
INNER JOIN images_by_product ibp
ON p.product_id = ibp.product_id
GROUP BY p.product_id

Мне удалось получить ваш точный вывод (кроме supplier_count, поскольку это не имело для меня смысла. Пожалуйста, объясните, если можете.

PRODUCT_ID     MIN_PRICE     IMAGE          SUPPLIER_ID  
1              9             'pencil.img'   1  
2              5             'paper.img'    1

ОБНОВЛЕНИЕ:

Это какой-то неудачный способ получить то, что вы хотите, но ... Это работает:

SELECT DISTINCT p.product_id, MIN(pbs.price), ibp.name, COUNT(pbs.supplier_id)
FROM product p
INNER JOIN images_by_product ibp
ON p.product_id = ibp.product_id
INNER JOIN price_by_supplier pbs
ON  p.product_id = pbs.product_id
GROUP BY  pbs.price
LIMIT 2


PRODUCT_ID     MIN_PRICE     IMAGE          SUPPLIER_ID  
2              5             'paper.img'     1  
1              9             'pencil.img'    3
0 голосов
/ 19 июля 2010

Вместо того, чтобы связываться со всеми этими ужасными объединениями, не могли бы вы попробовать что-то вроде ...

SELECT PRODUCT_ID,
       (SELECT MIN(PRICE)
             FROM PRICE_BY_SUPPLIER
             WHERE PRICE_BY_SUPPLIER.PRODUCT_ID = PRODUCT.PRODUCT_ID) AS MIN_PRICE,
       (SELECT NAME
             FROM PRODUCT_IMAGES
             WHERE PRODUCT_IMAGES.PRODUCT_ID = PRODUCT.PRODUCT_ID
             LIMIT 1) AS PRODUCT_IMAGES,
       (SELECT COUNT(*)
             FROM PRICE_BY_SUPPLIER
             WHERE PRICE_BY_SUPPLIER.PRODUCT_ID = PRODUCT.PRODUCT_ID) AS SUPPLIER_COUNT
    FROM PRODUCT_ID;
0 голосов
/ 19 июля 2010

Вы можете добавить еще одно объединение, чтобы получить изображение. Например, изображение max для каждого продукта:

SELECT  f.PRODUCT_ID, f.DESC, x.MIN_PRICE, x.SUPPLIER_COUNT, img.Name
FROM    ( 
        select  pp.PRODUCT_ID
        ,       MIN(pp.PRICE) as MIN_PRICE
        ,       COUNT(pp.PRODUCT_ID) as SUPPLIER_COUNT 
        from    PRICE_BY_SUPPLIER as pp 
        group by 
                pp.PRODUCT_ID
        ) AS x 
JOIN    PRODUCT as f 
on      f.PRODUCT_ID = X.PRODUCT_ID
JOIN    (
        select  max(name)
        from    images_by_product
        group by
                product_id
        ) as img
on      img.PRODUCT_ID = X.PRODUCT_ID

Если изображение не является обязательным, замените join на outer join. В зависимости от вашей СУБД, вы также можете получить случайное изображение. Например, в SQL Server вы можете заменить объединение на cross apply:

...
on      f.PRODUCT_ID = X.PRODUCT_ID
CROSS APPLY
        (
        select  top 1 name
        from    images_by_product
        where   PRODUCT_ID = X.PRODUCT_ID
        order by
                newid()
        ) as img

Или даже непосредственно в предложении select:

SELECT  f.PRODUCT_ID, f.DESC, x.MIN_PRICE, x.SUPPLIER_COUNT, img.Name
,       (
        select  top 1 name
        from    images_by_product
        where   PRODUCT_ID = X.PRODUCT_ID
        order by
                newid()
        ) as img
FROM    ( 
        select  pp.PRODUCT_ID
...
...