3

グループ化されたセットから最も古い/最も新しい行を 1 つ選択する方法を示す多くの例を見つけましたが、データ セットから最も古い 2 つの行を取得するのに問題があります。

これが私のサンプルテーブルです:

CREATE TABLE IF NOT EXISTS `orderTable` (
  `customer_id` varchar(10) NOT NULL,
  `order_id` varchar(4) NOT NULL,
  `date_added` date NOT NULL,
  PRIMARY KEY (`customer_id`,`order_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

INSERT INTO `orderTable` (`customer_id`, `order_id`, `date_added`) VALUES
('1234', '5A', '1997-01-22'),
('1234', '88B', '1992-05-09'),
('0487', 'F9', '2002-01-23'),
('5799', 'A12F', '2007-01-23'),
('1234', '3A', '2009-01-22'),
('3333', '7FHS', '2009-01-22'),
('0487', 'Z33', '2004-06-23'),
('3333', 'FF44', '2013-09-11'),
('3333', '44f5', '2013-09-02');

このクエリは 3 つ以上の行を返します。

SELECT customer_id, order_id, date_added
FROM orderTable T1
WHERE (
   select count(*) FROM orderTable T2
   where T2.order_id = T1.order_id AND T2.date_added <= T1.date_added
) <= 2;

単一の行を探しているわけではないため、これは標準greatest-n-per-groupタイプのクエリではありません。

各 customer_id の最初の 2 つの注文を取得できることについて何が欠けていますか?

4

4 に答える 4

0

これにより、目的の結果が生成されるはずですが、派生テーブルでフィルタリングしているため、アウターSELECTは最も効率的ではありません。

SELECT ranked.* 
FROM (
    SELECT ot.* , 
        @rownum := IF( ot.customer_id = @previous , @rownum +1, 1 ) rank, 
        @previous := ot.customer_id
    FROM orderTable ot, 
        (SELECT @rownum :=1, @previous := NULL) init
    ORDER BY customer_id, date_added
) ranked
WHERE rank <=2
于 2013-09-13T22:37:38.527 に答える