0

我在 MySQL 数据库中有三个相关的表:

  • inventory_items 定义仓库中的项目类型
  • inventory_transactions 定义添加或删除的库存数量
  • 位置定义所述库存的位置

Inventory_transactions 有一个 quantity_offset,用于存储从给定位置添加或删除了多少给定 inventory_item。

我有以下查询,它将获取 global_quantity(给定 inventory_item_id 的所有数量偏移的总和)以及 location_quantity,只要我知道位置 ID,它对特定位置执行相同操作。

SELECT sku, name, SUM(quantity_offset) AS global_quantity,
(
SELECT SUM(quantity_offset)
    FROM inventory_transactions
    WHERE inventory_items.inventory_item_id = inventory_transactions.inventory_item_id AND inventory_transactions.location_id = 1
) AS location_quantity
FROM inventory_items
JOIN inventory_transactions ON inventory_items.inventory_item_id = inventory_transactions.inventory_item_id
GROUP BY sku

我想要结束的是为每个位置添加一列,因此结果可能具有如下值:

sku, name, global_quantity, denver_quantity, dallas_quantity, ft_wayne_quantity

我的后备方案是在单个inventory_item 页面上执行此操作(当我知道库存项目并可以按位置分组时),但是能够在单个查询中执行此操作并将其全部放入一个表中会非常棒。

最初,我以为我可以遍历子查询,但无法以编程方式设置列名(在 AS 中)。

提前感谢您提供的任何帮助。

4

3 回答 3

1

顺便说一句,如果行来自给定位置,则可以在有条件地返回 quantity_offset 的表达式上使用 SUM 聚合获得相同的结果,而不是在 SELECT 列表中使用子查询。我还将使用 LEFT 外连接到 inventory_transactions 表,这样我就可以确保为 inventory_items 中的每一行返回一行:

SELECT i.sku
     , i.name
     , SUM(t.quantity_offset) AS global_quantity
     , SUM(IF(t.location_id = 1,t.quantity_offset,NULL)) AS location_1_quantity 
  FROM inventory_items i
  LEFT
  JOIN inventory_transactions t ON i.inventory_item_id = t.inventory_item_id
  GROUP BY i.sku

(这并不能回答你的问题,但我想让你意识到这一点。)

要回答您的问题,首先,SELECT 语句不可能动态更改它在结果集中返回的列的数量或类型。您需要为要返回的每一列定义一个表达式。(SQL SELECT 语句文本的生成可以动态完成,以生成特定的 SELECT 语句,但该 SELECT 语句返回的列由 SELECT 语句固定。)

如果我有一组相对固定的 location_id 值,并且我需要您指定的结果集,我将多次重复条件表达式的 SUM,对于每个位置或我想要的任何位置集一次:

SELECT i.sku
     , i.name
     , SUM(t.quantity_offset) AS global_quantity
     , SUM(IF(t.location_id = 1,t.quantity_offset,NULL)) AS location_1_quantity 
     , SUM(IF(t.location_id = 2,t.quantity_offset,NULL)) AS location_2_quantity 
     , SUM(IF(t.location_id = 3,t.quantity_offset,NULL)) AS location_3_quantity 
     , SUM(IF(t.location_id IN (1,2,3),t.quantity_offset,NULL)) AS location_123_quantity 
     , SUM(IF(t.location_id = 4,t.quantity_offset,NULL)) AS location_4_quantity
  FROM inventory_items i
  LEFT
  JOIN inventory_transactions t ON i.inventory_item_id = t.inventory_item_id
  GROUP BY i.sku

如果要返回的列集需要真正动态,那么我根本不会将它们作为列返回。相反,我会将每个位置的 SUM(quantity_offset) 作为单独的行返回,然后在客户端将转换处理为按列表示。

于 2013-02-22T20:25:38.687 回答
1

您应该使用条件和 - 这是我所知道的最有效的方式(最快的查询):

SELECT sku, name, SUM(quantity_offset) AS global_quantity,
  sum(case when inventory_transactions.location_id = 1 then quantity_offset else 0 end) as  loc1_quantitity,
  sum(case when inventory_transactions.location_id = 2 then quantity_offset else 0 end) as loc2_quantitity,
  sum(case when inventory_transactions.location_id = 3 then quantity_offset else 0 end) as loc3_quantitity
FROM inventory_items JOIN inventory_transactions ON inventory_items.inventory_item_id = inventory_transactions.inventory_item_id
GROUP BY sku
于 2013-02-22T20:25:57.703 回答
0

试试这个

   SELECT sku, name, SUM(quantity_offset) AS global_quantity,
       (
        SELECT SUM(quantity_offset)
         FROM inventory_transactions
           WHERE inventory_items.inventory_item_id = inventory_transactions.inventory_item_id AND inventory_transactions.location_id = 1
          AND location = denver) AS denver_quantity ,
        (
        SELECT SUM(quantity_offset)
         FROM inventory_transactions
           WHERE inventory_items.inventory_item_id = inventory_transactions.inventory_item_id AND inventory_transactions.location_id = 1
          AND location = dallas) AS dallas_quantity,
         (
        SELECT SUM(quantity_offset)
         FROM inventory_transactions
           WHERE inventory_items.inventory_item_id = inventory_transactions.inventory_item_id AND inventory_transactions.location_id = 1
          AND location = ft_wayne) AS ft_wayne_quantity
   FROM inventory_items
   JOIN inventory_transactions ON inventory_items.inventory_item_id = inventory_transactions.inventory_item_id
   GROUP BY sku

请注意,我用作location列名我不知道您拥有的位置的列名,只需替换它

于 2013-02-22T20:12:54.657 回答