7

我有一个包含产品订单表的数据库,如下所示:

order_id | prod_code | prod_color | size | quantity |  
-----------------------------------------------------
1          SHIRT       001          S      10
1          SHIRT       001          M      7
1          SHIRT       001          L      8
1          SHIRT       001          XL     1
1          SHIRT       995          S      2
1          SHIRT       995          M      1
1          SHIRT       995          L      0
1          SHIRT       995          XL     1
2          PANTS       ....

和这样的产品价格表:

prod_code | prod_color | price | currency
-----------------------------------------
SHIRT       001          10      EUR
SHIRT       001          9       USD
SHIRT       001          50      YEN
SHIRT       001          15      RUB
SHIRT       995          20      EUR
SHIRT       995          29      USD
SHIRT       995          100     YEN
SHIRT       995          45      RUB 
PANTS       ....  

我想要得到的是这样的视图(为简单起见,按 order_id 过滤):

order_id | prod_code | prod_color | size | quantity | EUR | USD | YEN | RUB
---------------------------------------------------------------------------
1          SHIRT       001          S      10         10    9     50    15
1          SHIRT       001          M      7          10    9     50    15
1          SHIRT       001          L      8          10    9     50    15
1          SHIRT       001          XL     1          10    9     50    15
1          SHIRT       995          S      2          20    29    100   45
1          SHIRT       995          M      1          20    29    100   45
1          SHIRT       995          L      0          20    29    100   45
1          SHIRT       995          XL     1          20    29    100   45

我已经浏览了网络和 SO,我发现这个问题向我展示了我需要做什么,但我认为有一些修改......

我尝试在数据库上运行此查询:

SELECT o.order_id, o.prod_code, o.prod_color, o.size, o.quantity,
MAX(CASE WHEN p.currency = 'EUR' THEN p.price END) AS 'EUR',
MAX(CASE WHEN p.currency = 'USD' THEN p.price END) AS 'USD',
MAX(CASE WHEN p.currency = 'YEN' THEN p.price END) AS 'YEN',
MAX(CASE WHEN p.currency = 'RUB' THEN p.price END) AS 'RUB'
FROM products_order o JOIN products_prices p ON o.prod_code = p.prod_code
WHERE o.order_id = 1
GROUP BY o.order_id, o.prod_code, o.prod_color, o.size, o.quantity

将在价格列中返回,对于每一行,在整个列中找到的 MAX 值:所以对于 [product_color = 001] 和 [product_color = 995] 我的价格都等于 20 欧元(当 001 更便宜时,只有10欧元!)

我也尝试过不使用 MAX,但它为每个价格提供了一行,使许多单元格为空(然后我明白了 MAX 的用途:D)。

你知道一种方法来做我想做的事吗?如何在单个 prod_color 中使用 MAX,而不是通过每个 prod_color 使用?

我希望你能理解我写的东西,在此先感谢,任何帮助表示赞赏。

(如果您需要更清楚的解释,请询问并尽快回复。

再次感谢,最好的问候

4

2 回答 2

11

我添加了一个额外的JOIN条件:AND o.prod_color = p.prod_color

http://sqlfiddle.com/#!5/fadad/5

SELECT
  o.order_id, o.prod_code, o.prod_color, o.size, o.quantity,
  MAX(CASE WHEN p.currency = 'EUR' THEN p.price END) AS 'EUR',
  MAX(CASE WHEN p.currency = 'USD' THEN p.price END) AS 'USD',
  MAX(CASE WHEN p.currency = 'YEN' THEN p.price END) AS 'YEN',
  MAX(CASE WHEN p.currency = 'RUB' THEN p.price END) AS 'RUB'

FROM products_order o
JOIN products_prices p
  ON o.prod_code = p.prod_code
 AND o.prod_color = p.prod_color /* this line is added */

WHERE o.order_id = '1'
GROUP BY
  o.order_id,
  o.prod_code,
  o.prod_color,
  o.size,
  o.quantity

GROUP BY没有显示差异的简化示例查询:

http://sqlfiddle.com/#!5/fadad/13

于 2012-08-03T17:31:14.120 回答
0

动态查询方法(CASE每个数据透视列都有表达式)应该是首选的方法,但是当您预先不知道数据透视列或者由于某种原因很难在应用程序端生成查询时,可以使用 pivot_vtab 形式的替代方法SQLite 虚拟表扩展。在撰写本文时它不太实用,因为它似乎是一项概念验证工作,但这并不意味着它可以/不会改进。

我不会详细介绍如何构建扩展——您可以在这个相关的答案中看到它们。我正在使用这样的问题中的数据。

CREATE TABLE products_order(
  order_id INTEGER,
  prod_code TEXT,
  prod_color INTEGER,
  size TEXT,
  quantity INTEGER
);

INSERT INTO products_order(order_id, prod_code, prod_color, size, quantity)
VALUES
  (1, 'SHIRT', 001, 'S', 10),  (1, 'SHIRT', 001, 'M', 7),
  (1, 'SHIRT', 001, 'L', 8),   (1, 'SHIRT', 001, 'XL', 1),
  (1, 'SHIRT', 995, 'S', 2),   (1, 'SHIRT', 995, 'M', 1),
  (1, 'SHIRT', 995, 'L', 0),   (1, 'SHIRT', 995, 'XL', 1);

CREATE TABLE products_prices(
  prod_code TEXT,
  prod_color INTEGER,
  price INTEGER,
  currency TEXT
);

INSERT INTO products_prices(prod_code, prod_color, price, currency)
VALUES
  ('SHIRT', 001, 10, 'EUR'),  ('SHIRT', 001, 9, 'USD'),
  ('SHIRT', 001, 50, 'YEN'),  ('SHIRT', 001, 15, 'RUB'),
  ('SHIRT', 995, 20, 'EUR'),  ('SHIRT', 995, 29, 'USD'),
  ('SHIRT', 995, 100, 'YEN'), ('SHIRT', 995, 45, 'RUB');

枢轴是这样构建的(我假设扩展已加载,.load ./pivot_vtab)。

  1. 因为扩展仅限于一个“行”列(您在其上分组),所以创建一个临时映射。我假设 order 键在功能(order_id, prod_code, prod_color, size)quantity取决于order_id,因此无需对其进行分组,但它将在第 3 步中使用。

    CREATE TABLE rowmap AS 
    SELECT 
      ROW_NUMBER() OVER(ORDER BY 1) row_id, 
      order_id,  
      prod_code,  
      prod_color,  
      size, 
      quantity
    FROM products_order
    GROUP BY 2, 3, 4, 5;
    
  2. pivot使用表创建rowmap表。请注意,第三个枢轴“矩阵填充”查询也只需要单列。

    CREATE VIRTUAL TABLE pivot USING pivot_vtab(
      (SELECT row_id FROM rowmap),
      (SELECT currency, currency FROM products_prices GROUP BY currency),   
      (
        SELECT price
        FROM products_order o
        JOIN products_prices p USING(prod_code, prod_color)
        JOIN rowmap m USING(order_id, prod_code, prod_color, size)
        WHERE o.order_id = 1 AND m.row_id = ?1 AND p.currency = ?2
        GROUP BY o.order_id, o.prod_code, o.prod_color, o.size, p.currency
      )
    );
    
  3. 重新组合rowmap列。

    SELECT order_id, prod_code, prod_color, size, quantity, p.*
    FROM pivot p
    JOIN rowmap r ON p.row_id = r.row_id;
    

    结果集应如下所示(我有.headers on.mode column)。

    order_id    prod_code   prod_color  size        quantity    row_id      EUR         RUB         USD         YEN       
    ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------
    1           SHIRT       1           L           8           1           10          15          9           50        
    1           SHIRT       1           M           7           2           10          15          9           50        
    1           SHIRT       1           S           10          3           10          15          9           50        
    1           SHIRT       1           XL          1           4           10          15          9           50        
    1           SHIRT       995         L           0           5           20          45          29          100       
    1           SHIRT       995         M           1           6           20          45          29          100       
    1           SHIRT       995         S           2           7           20          45          29          100       
    1           SHIRT       995         XL          1           8           20          45          29          100  
    
  4. 或者,如果您想删除该row_id列,您可以使用另一个临时表删除它(ALTER TABLE ... DROP COLUMN自 SQLite 3.35 起支持)。

    CREATE TABLE result_pivot AS 
    SELECT order_id, prod_code, prod_color, size, quantity, p.*
    FROM pivot p
    JOIN rowmap r ON p.row_id = r.row_id;
    
    ALTER TABLE result_pivot DROP COLUMN row_id;
    
    SELECT * FROM result_pivot;
    
于 2021-05-16T14:00:53.160 回答