1

Orders (注文ごとに 1 つのレコード) を含むテーブルと、OrderDetails (注文の製品ごとに 1 つのレコード) を含むテーブルがあります。SELECT ステートメントで、ProductID で名前が付けられた列に各製品の数量を返すようにしたいと考えています。このように、ProductID ごとに明示的にクエリを記述するわけではありませんが、クエリが OrderDetails テーブルで見つかった ProductID に適応するようにします。

結果は次のようになります。

OrderID   TrackingNr   ProductID1   ProductID2   ProductID3
1         1Zetc        6            0            2
2         1Zetc2       0            1            1

現在、次のものがあります。

SELECT Orders.OrderID AS OrderID,
TrackingNumbers.TrackingNumber AS TrackingNumber,
(SELECT Quantity FROM OrderDetails WHERE Orders.OrderID = OrderDetails.OrderID AND ProductCode = 'FPIA0009') AS FPIA0009,
(SELECT Quantity FROM OrderDetails WHERE Orders.OrderID = OrderDetails.OrderID AND ProductCode = 'FPIA0030') AS FPIA0030,
((SELECT Quantity FROM OrderDetails WHERE Orders.OrderID = OrderDetails.OrderID AND ProductCode = 'FPIA0060') +
(SELECT Quantity FROM OrderDetails WHERE Orders.OrderID = OrderDetails.OrderID AND ProductCode = 'FPIA0060xP')) AS FPIA0060,
(SELECT Quantity FROM OrderDetails WHERE Orders.OrderID = OrderDetails.OrderID AND ProductCode = 'FPIA0120') AS FPIA0120
FROM Orders, TrackingNumbers WHERE Orders.OrderID = TrackingNumbers.OrderID
ORDER BY OrderID, ShipDate

ご覧のとおり、上記では特定の ProductID ごとに数量を明示的に要求していますが、他にも多くの数量があり、単純化したいと考えています。

ご覧のとおり、2 つの異なる製品の数量を合計しようとしましたが、これらは同じ在庫から抽出されたものでしたが、何らかの理由で結果が常に空になっています。

あなたの助けは大歓迎です!

4

2 に答える 2

1

MySQL にはPIVOT関数がありませんが、集計関数とCASEステートメントを使用してモデル化できます。動的バージョンの場合、準備済みステートメントを使用する必要があります。

使用されるサンプル テーブル:

create table orders
(
  id int,
  name varchar(10)
);

insert into orders values
(1, 'Order 1'),
(2, 'Order 2'),
(3, 'Order 3'),
(4, 'Order 4');

create table orderdetails
(
  orderid int,
  productname varchar(20),
  qty int
);

insert into orderdetails values
(1, 'Product 1', 10),
(1, 'Product 2', 1),
(1, 'Product 3', 45),
(2, 'Product 1', 2),
(2, 'Product 5', 78),
(3, 'Product 4', 60),
(3, 'Product 2', 32),
(4, 'Product 1', 5),
(4, 'Product 3', 6),
(5, 'Product 2', 9),
(6, 'Product 4', 1);

create table trackingnumbers
(
  orderid int,
  trackingnumber varchar(10)
);

insert into trackingnumbers values
(1, '1Zetc'),
(2, '1Zdfghfdg'),
(3, '1Zkyui'),
(4, '1Zwe');

列として必要な値の数がわかっている場合は、次のように値をハードコーディングできます。

select o.id,
  t.trackingnumber,
  sum(case when productname = 'Product 1' then qty else 0 end) Product1,
  sum(case when productname = 'Product 2' then qty else 0 end) Product2,
  sum(case when productname = 'Product 3' then qty else 0 end) Product3,
  sum(case when productname = 'Product 4' then qty else 0 end) Product4,
  sum(case when productname = 'Product 5' then qty else 0 end) Product5
from orders o
left join orderdetails d
  on o.id = d.orderid
left join trackingnumbers t
  on o.id = t.orderid
group by o.id, t.trackingnumber;

デモで SQL Fiddle を参照してください

ただし、値の数が不明な場合は、準備済みステートメントを使用できます。

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'sum(case when productname = ''',
      productname,
      ''' then qty else 0 end) AS ',
      replace(productname, ' ', '')
    )
  ) INTO @sql
FROM orderdetails;


SET @sql = CONCAT('SELECT o.id, t.trackingnumber, ', @sql, ' 
                  from orders o
                  left join orderdetails d
                    on o.id = d.orderid
                  left join trackingnumbers t
                    on o.id = t.orderid
                  group by o.id, t.trackingnumber');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

デモで SQL Fiddle を参照してください

于 2012-10-16T10:10:05.023 に答える
0

なぜそのようにしたいのかわかりませんが、いつでも Cursor を使用して SQL を作成し、実行することができます。そうすれば、少なくともハードコードされません。ただし、列名に値を使用しないことをお勧めします。

于 2012-10-16T02:55:59.173 に答える