MySQL:SQL Query返回两个不同的最小值

时间:2017-12-14 00:09:47

标签: mysql

我有3个MySQL表:

items
id      |  title
 1      |  The Matrix DVD
 2      |  Star Wars DVD


itemListings
// condition_id 1 = New, 2 = Used
id  |item_id| condition_id
 1  |   2   |   2 
 2  |   2   |   1
 3  |   2   |   1
 4  |   2   |   1
 5  |   2   |   2
 6  |   2   |   2
 8  |   2   |   2
 9  |   1   |   1   


itemListings_inventory
id  | listing_id | start_price
 1  |   1        |   4.00
 2  |   2        |  12.00
 3  |   3        |  14.00
 4  |   4        |  15.00
 5  |   5        |   6.00
 6  |   6        |   7.00
 7  |   8        |  11.00
 8  |   8        |   9.00
 9  |   8        |   2.00
10  |   8        |  13.00
11  |   9        |   5.00

如果用户搜索"星球大战",我需要返回:

item_id |  title        | lowest_new_price   | lowest_used_price 
   2    | Star Wars DVD |   12.00            |       2.00

到目前为止,我有这个只返回lowest_used_price的SQL:

SELECT 
items.id,
items.title,
MIN(start_price) AS lowest_used_price
FROM itemListings_inventory
JOIN itemListings ON itemListings_inventory.listing_id = itemListings.id
JOIN items ON itemListings.item_id = items.id
WHERE itemListings.condition_id = 2
AND MATCH (items.title, items.description) AGAINST ('star wars') 
GROUP BY items.id

但我怎么能得到lowest_new_price和lowest_used_price?

更新:有些商品会有新价格和二手价格,有些商品只有新价格,有些商品只有二手价格。

3 个答案:

答案 0 :(得分:1)

思考练习:

您的itemlistings表,它包含新旧项目,对吗?而您的查询基本上是如何获得最低使用价格和最低新价格。

如果使用的项目在一个表格中,并且新项目在另一个表格中(因此两个单独的列表表而不是您的一个表格),您能否这样做?

大概..

因此,答案就是概念性地将列表表分成两部分,将其放入查询中两次,一次换新,一次换旧。通过使用子查询,这是最容易设想的:

SELECT * FROM
Items
INNER JOIN
(
 SELECT 
  ItemListings.id,
  MIN(start_price) AS lowest_used_price
 FROM 
  itemListings_inventory
  JOIN itemListings ON itemListings_inventory.listing_id = itemListings.id
 WHERE itemListings.condition_id = 2
 GROUP BY items.id 
)used
ON items.id = used.id

INNER JOIN
(
  SELECT 
   items.id,
   MIN(start_price) AS lowest_new_price
  FROM 
   itemListings_inventory
   JOIN itemListings ON itemListings_inventory.listing_id = itemListings.id
  WHERE itemListings.condition_id = 1
  GROUP BY items.id
) nu
ON items.id = nu.id

你也可以通过一个名为pivoting的方法来实现它,你可以在其中加入一次,但是使用条件只选择有趣的行,然后将它们分组:

SELECT 
  items.id,
  items.title,
  MIN(CASE WHEN condition_id = 2 THEN start_price END) AS lowest_used_price,
  MIN(CASE WHEN condition_id = 1 THEN start_price END) AS lowest_new_price
FROM 
  itemListings_inventory
  JOIN itemListings ON itemListings_inventory.listing_id = itemListings.id
  JOIN items ON itemListings.item_id = items.id

GROUP BY items.id, items.title

要了解更多相关信息,请运行以下命令:

SELECT items.id, items.title,
  CASE WHEN condition_id = 2 THEN start_price END AS used_price,
  CASE WHEN condition_id = 1 THEN start_price END AS new_price
FROM 
  itemListings_inventory
  JOIN itemListings ON itemListings_inventory.listing_id = itemListings.id
  JOIN items ON itemListings.item_id = items

并且知道MIN选择最低的非空值

注意,我还没有在这些查询中添加任何WHERE item.id = 2WHERE items.title LIKE '%star wars%'(即只有星球大战行);我认为你可以自己做那部分(无论如何你不太可能想要将星球大战硬编码为你的代码搜索的唯一一种DVD);这更多的是关于运行两次连接表的基本技术,如果它有想要出现在同一结果行上的东西,尽管表中有不同的行...以及使用CASE WHEN的其他技术将不感兴趣的行减少为null,以便MIN将忽略它们。

答案 1 :(得分:0)

它可以更有效,但这应该有用。

SELECT new.id, new.title, new.lowest_new_price, used.lowest_used_price
FROM (
    SELECT 
    items.id,
    items.title,
    MIN(start_price) AS lowest_new_price
    FROM itemListings_inventory
    JOIN itemListings ON itemListings_inventory.listing_id = itemListings.id
    JOIN items ON itemListings.item_id = items.id
    WHERE itemListings.condition_id = 1
    AND MATCH (items.title, items.description) AGAINST ('star wars') 
    GROUP BY items.id
) new
JOIN (
    SELECT 
    items.id,
    items.title,
    MIN(start_price) AS lowest_used_price
    FROM itemListings_inventory
    JOIN itemListings ON itemListings_inventory.listing_id = itemListings.id
    JOIN items ON itemListings.item_id = items.id
    WHERE itemListings.condition_id = 2
    AND MATCH (items.title, items.description) AGAINST ('star wars') 
    GROUP BY items.id
) used ON used.id = new.id

答案 2 :(得分:0)

通过解决方案分组对我来说比较为一般。我做这样的事情:

SELECT x.id, x.title, SUM(IF(x.conditionId = 1, x.price, 0)) lowest_new_price, SUM(IF(x.conditionId = 2, x.price, 0)) lowest_used_price
 (  SELECT i.id, i.title, iL.conditionId, MIN(iLI.start_price) price  FROM items i, itemListings iL, itemListings_inventory iLI
     WHERE i.title = 'Star Wars'
       AND i.id = iL.id
       AND iL.id = iLI.listing_id 
  GROUP BY i.id, i.title, iL.conditionId) x
GROUP BY i.id, i.title

条件总和从子查询中挑选出conditon_id分组的最低价格。