0

我有三张桌子:

Shop_Table
   shop_id
   shop_name

Sells_Table
   shop_id
   item_id
   price

Item_Table
   item_id
   item_name

通过Sells_TableFK 将项目和商店表链接到它们的 ID。我正在尝试从每家商店获取最昂贵的商品,即表单的输出:

(shop_name, item_name, price)
(shop_name, item_name, price)
(shop_name, item_name, price)
(shop_name, item_name, price)
...

其中价格是每个商店的最高价格项目。我似乎可以实现 (shop_name, max(price)) 但是当我尝试包含 item_name 时,我得到了 shop_name 的多个条目。我目前的方法是

create view shop_sells_item as
select s.shop_name as shop, i.item_name as item, price
from Shop_Table s
join Sells_Table on (s.shop_id = Sells_Table.shop_id)
join Item_Table i on (i.item_id = Sells_Table.item_id);

select shop, item, max(price)
from shop_sells_item
group by shop;

但是,我收到一条错误消息item must appear in the GROUP BY clause or be used in an aggregate function,但如果我包含它,那么我不会获得每家商店的最高价格,而是获得每家商店的最高价格,这是没有用的物品对。

另外,使用视图是最好的方法吗?可以通过单个查询完成吗?

4

5 回答 5

2

你可以用 Postgresql 的方式来做:

select distinct on (shop_name) shop_name, item_name, price 
from shop_table
join sells_table using (shop_id) 
join item_table using (item_id)
order by shop_name, price;
于 2013-09-28T10:56:25.977 回答
1

请注意,下面的查询不处理一个商店中的多个商品具有相同最高价格的情况(它们都是最昂贵的):

SELECT
    s.shop_name,
    i.item_name,
    si.price
FROM
    Sells_Table si
JOIN
    Shop_Table s
ON
    si.shop_id = s.shop_id
JOIN
    Item_Table i
ON
    si.item_id = i.item_id
WHERE
    (shop_id, price) IN (
        SELECT
            shop_id,
            MAX(price) AS price_max
        FROM
            Sells_Table
        GROUP BY
            shop_id
    );
于 2013-09-28T12:25:42.607 回答
1

可能最快:

SELECT s.shop_name, i.item_name, sub.price
FROM  (
   SELECT DISTINCT ON (shop_id) shop_id, item_id, price 
   FROM   sells_table
   ORDER  BY shop_id, price DESC -- , item_id -- for 1 item only
   ) sub
JOIN   item_table i USING (item_id)
JOIN   shop_table s USING (shop_id);
  • 要得到the most expensive item from each store你必须ORDER BY .. price DESC

  • 上面的查询为您提供了共享最高价格的商店的所有商品。可以不止一个。如果你总是想要一个项目,你必须定义如何打破关系。例如,取消注释ORDER BY上面的附加项目以选择具有 minimum 的项目item_id

  • 首先聚合(或选择)然后加入与聚合或选择本身无关的其他表通常更快。

DISTINCT ON此相关答案中的详细信息:
选择每个 GROUP BY 组中的第一行?

您可以轻松地从上述查询创建一个VIEW,性能与原始 SQL 大致相同。

最佳表现指数

如果你想要那么,请尝试如下的多列索引:

CREATE INDEX sells_table_special_idx
ON sells_table (shop_id, price DESC, item_id)

注意第二列的降序。
第三列仅用于使其成为覆盖索引,仅适用于 PostgreSQL 9.2 或更高版本。

于 2013-09-28T13:17:22.767 回答
1

我想从每家商店买到最贵的东西,

一家商店最贵商品的定义:= 这家商店没有更贵的商品

SELECT *
FROM Sells_Table st
WHERE NOT EXISTS (
    SELECT * FROM Sells_Table nx
    WHERE nx.shop_id = st.shop_id
    AND nx.price > st.price
);

现在我们有了与您想要的项目相对应的 sells_table 条目:结果集的骨架。只需添加

SELECT sh.shop_name -- <<-- Meat
    , it.item_name  -- <<-- Meat
    , st.price
FROM Sells_Table st
JOIN shop_table sh ON sh.shop_id = st.shop_id  -- <<-- Meat
JOIN items_table it ON it.item_id = st.item_id -- <<-- Meat
WHERE NOT EXISTS (
    SELECT * FROM Sells_Table nx
    WHERE nx.shop_id = st.shop_id
    AND nx.price > st.price
);
于 2013-09-28T11:55:20.087 回答
0

你的问题听起来有点奇怪,但让我看看我是否可以改写它。

对于每家商店,我想找到他们卖的最贵的东西。从该项目中,您需要它的名称、价格和销售它的商店。但是,您还声明您正在使用 MIN() 作为最低价格......它是最高价格还是最低价格。无论哪种方式,只需更改 min() 与 max()

首先从商店和他们销售的最高价格(或最低)商品开始——不管它是什么

选择 shop_id, max(price) 仅按 shop_id 分组...以此为基础,然后获取与此最高价格匹配的商品...一家商店可能有 10 件商品,价格为 199 美元,而您没有任何身份信息只想要 1 和处理它的标准。我得到了

select
      FindingMax.Shop_id,
      shop.shop_name,
      FindingMax.HighestPrice,
      Item_Table.item_name
   from
      ( select st.shop_id,
               max( st.price ) as HighestPrice
           from
               sells_table st
           group by
               st.shop_id ) as FindingMax
      JOIN Shop_Table shop
         on FindingMax.shop_id = shop.shop_id
      JOIN sells_table st2
         on FindingMax.shop_id = st2.shop_id
         AND FindingMax.HighestPrice = st2.price
         JOIN Item_Table
            on st2.item_id = Item_Table.item_id
于 2013-09-28T11:31:26.263 回答