【问题标题】:Subquery and selecting oldest rows for multiple foreign keys in MySQL子查询并为 MySQL 中的多个外键选择最旧的行
【发布时间】:2011-01-25 11:02:33
【问题描述】:

我有两张桌子:

product (idproduct, name, description, tax)

product_storage (idstorage, idproduct, added, quantity, price)

对于每种产品,它可能有不同的价格,最早的产品是“最先销售”

例如在我的存储中:

1, 1, 2010-01-01,  0, 10.0
2, 1, 2010-01-02,  0, 11.0
3, 1, 2010-01-03, 10, 12.0
4, 2, 2010-01-04,  0, 12.0
5, 2, 2010-01-05, 10, 11.0
6, 2, 2010-01-06, 10, 13.0
7, 3, 2010-01-07, 10, 14.0
8, 3, 2010-01-08, 10, 16.0
9, 3, 2010-01-09, 10, 13.0

现在我需要选择当前价格的所有产品,它位于 product_storage 中最旧的行中,其中每个产品的数量 > 0:

SELECT p.idproduct, p.name, p.tax,
       (SELECT s.price
        FROM product_storage s
        WHERE s.idproduct=p.idproduct AND s.quantity > 0
        ORDER BY s.added ASC
        LIMIT 1) AS price
FROM product p;

工作正常,但当我想在查询中计算含税价格时却不行:

SELECT p.idproduct, p.name, p.tax,
       (SELECT s.price
        FROM product_storage s
        WHERE s.idproduct=p.idproduct AND s.quantity > 0
        ORDER BY s.added ASC
        LIMIT 1) AS price,
        (price * (1 + tax/100)) AS price_with_tax
FROM product p;

MySQL 说:

Unknown column 'price' in 'field list'

更新

使用子查询作为表几乎可以解决问题(查看答案)——现在唯一的问题是如何从 product_storage 中为多个外键选择最旧的行(每个 idproduct 一个且只有一个)。

更新 2

感谢 cmptrgeekken 提供了很好的解决方案 :))

【问题讨论】:

    标签: sql mysql subquery


    【解决方案1】:

    这几乎可以正常工作:

    SELECT p.idproduct, p.name, p.tax,
           sub.price, (sub.price * (1+tax/100)) as price_with_tax
    FROM product p,
        (SELECT s.idproduct, s.price
         FROM product_storage s
         WHERE quantity > 0
         ORDER BY added ASC) sub
    WHERE p.idproduct=sub.idproduct
    

    但是 product_storage 中的所有行都会为每个产品返回:/

    【讨论】:

      【解决方案2】:

      就 MySQL 而言,最后出现的单词“price”指的是 Product p 中的一个字段,因此出现了错误。您需要再次参考上面的别名子查询:

      SELECT p.idproduct, p.name, p.tax,
             (SELECT s.price
              FROM product_storage s
              WHERE s.idproduct=p.idproduct AND s.quantity > 0
              ORDER BY s.added ASC
              LIMIT 1) AS price,
              (       (SELECT s.price
              FROM product_storage s
              WHERE s.idproduct=p.idproduct AND s.quantity > 0
              ORDER BY s.added ASC
              LIMIT 1) * (1 + tax/100)) AS price_with_tax
      FROM product p;
      

      【讨论】:

      • 'product' 表中没有任何 'price' 字段 - 您确定这个重复的子查询没有重新计算吗?
      • 那是我未能在我的帖子中说清楚的一点。您不能使用别名字段来计算税值,因为 MySQL 正在 Product 表中查找“价格”列。所以我写的内容再次明确要求 Product_Storage 的计算值。无论如何,我认为 PowerLord 的答案更好(去看看。)
      【解决方案3】:

      将子查询用作表可能会更好:

      SELECT p.idproduct, p.name, p.tax, s.price, (s.price * (1 + p.tax/100)) as price_with_tax
      FROM product p
      INNER JOIN (SELECT idproduct, price
              FROM product_storage
              WHERE quantity > 0) s
      ON p.idproduct = s.idproduct
      INNER JOIN (SELECT idproduct, MIN(added) min
              FROM product_storage
              GROUP BY idproduct) f
      ON s.idproduct = f.idproduct AND s.added = f.min
      

      编辑:已更新,因为税在另一个表中,所以我不得不移动该计算的位置。

      编辑 2:好的,再次更改以尝试正确过滤 product_storage 表。

      【讨论】:

      • “‘字段列表’中的未知列‘税’”
      • 也许我应该对表进行非规范化并在 product_storage 中重复税收数据?
      • @Marek:哦,哎呀,税在另一张桌子上不是吗。
      • 是的......但仍然不行 - LIMIT 1 子查询是一个有 1 行的表,没有它的所有行 WHERE 数量 > 0... 特别是它有超过 1 行每种产品(价格不同)——看看我对这个问题的第一个回答;)
      • @Marek:我应该想到这一点。可以修复,但查询可能会变得更复杂。
      【解决方案4】:

      您收到price doesn't exist 错误的原因是您无法在列列表中引用别名列。要解决此问题,请将 price 值存储在用户定义的变量中并引用它,如下所示:

      SELECT p.idproduct, p.name, p.tax,
             @price := (SELECT s.price
              FROM product_storage s
              WHERE s.idproduct=p.idproduct AND s.quantity > 0
              ORDER BY s.added ASC
              LIMIT 1) AS price,
              (@price * (1 + tax/100)) AS price_with_tax
      FROM product p;
      

      【讨论】:

        【解决方案5】:

        首先,您希望获得产品的最低存储 ID。

        SELECT idproduct, MIN(idstorage) idstorage FROM product_storage 
        WHERE quantity>0 AND idproduct IN (#, #, ...)
        GROUP BY idstorage
        

        idstorage、idproduct、添加、数量、价格 然后,您可以使用最小存储 ID 加入该查询和 product_storage 表(再次),以获取具有正确定价信息的产品信息。

        SELECT idproduct, name, description, tax, ps.price, ps.quantity,
        FROM product AS p
        JOIN 
        (SELECT idproduct, MIN(idstorage) idstorage FROM product_storage 
        WHERE quantity>0 AND idproduct IN (#, #, ...)
        GROUP BY idstorage) AS min_id
        ON p.idproduct=min_id.idproduct
        RIGHT JOIN product_storage AS ps ON ps.idstorage=min_id.idstorage
        WHERE idproduct IN (#, #, ...)
        

        【讨论】:

        • "... idproduct IN (#, #, ...) ..." - 没有指定 idproduct - 例如我采用最新产品、X 类产品等。
        猜你喜欢
        • 1970-01-01
        • 2014-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-01
        • 1970-01-01
        • 2014-06-29
        相关资源
        最近更新 更多