2

最新の日付、次の日付、およびその後の日付に対応する行を見つけるのに助けが必要です.ABCが「Y」であり、列名XYZ ASCでグループ化しますが、XYZは複数回表示されます. したがって、XYZ が 50 であるとすると、3 年間の行の場合、XYZ は 50 になります。次のコードは実行されますが、数千行のうち 2 行しか返されませんが、これは不可能です。日付条件だけを実行しようとしましたが、MAX(DATE)-3 以下の日付も返されました。どこが間違っているのかわかりません。

select * from money.cash where DATE =(
  select
  MAX(DATE)
  from
  money.cash
  where
  DATE > (select MAX(DATE)-3 from money.cash)
)
GROUP BY XYZ ASC
having ABC = "Y";

テーブルの構造は以下のとおりです(あくまで模式図であり、実物ではありません)。

Comp_ID   DATE   XYZ   ABC  $$$$ ....
1     2012-1-1    10    Y   SOME-AMOUNT
2     2011-1-1    10    Y
3     2006-1-1    10    Y
4     2011-1-1    20    Y
5     2002-1-1    20    Y
6     2000-1-1    20    Y
7     1998-1-1    20    Y

必要な o/p は、XYZ=10 の場合は最初の 3 行を昇順で、XYZ=20 の場合は最新の 3 つの日付になります。

最後で重要 - このテーブルの値は、新しいデータが入ってくると変化し続けます。そのため、o/p (新しいテーブルに含まれる) は、最初の/元の/上のテーブルのダイナミクスを反映する必要があります。

4

2 に答える 2

1

greatest-n-per-groupMySQLには、クエリに適した機能がありません。

1つのオプションは次のようになります...-グループごと
に検索 -次に、その結​​果を使用して、その日付より前のすべてのレコードを検索します -次に、その日付より前のすべてのレコードに対して再度実行します MAX(Date)XYZ
MAX(Date)

これは本当に非効率的ですが、MySQLにはこれを効率的に行うために必要な機能がありません。ごめん...

CREATE TABLE yourTable
     (
      comp_id                          INT,
      myDate                           DATE,
      xyz                              INT,
      abc                              VARCHAR(1)
)
;

INSERT INTO yourTable SELECT 1, '2012-01-01', 10, 'Y';
INSERT INTO yourTable SELECT 2, '2011-01-01', 10, 'Y';
INSERT INTO yourTable SELECT 3, '2006-01-01', 10, 'Y';
INSERT INTO yourTable SELECT 4, '2011-01-01', 20, 'Y';
INSERT INTO yourTable SELECT 5, '2002-01-01', 20, 'Y';
INSERT INTO yourTable SELECT 6, '2000-01-01', 20, 'Y';
INSERT INTO yourTable SELECT 7, '1998-01-01', 20, 'Y';


SELECT
  yourTable.*
FROM
(
  SELECT
    lookup.XYZ,
    COALESCE(MAX(yourTable.myDate), lookup.MaxDate)  AS MaxDate
  FROM
  (
    SELECT
      lookup.XYZ,
      COALESCE(MAX(yourTable.myDate), lookup.MaxDate)  AS MaxDate
    FROM
    (
      SELECT
        yourTable.XYZ,
        MAX(yourTable.myDate)  AS MaxDate
      FROM
        yourTable
      WHERE
        yourTable.ABC = 'Y'
      GROUP BY
        yourTable.XYZ
    )
      AS lookup
    LEFT JOIN
      yourTable
        ON  yourTable.XYZ    = lookup.XYZ
        AND yourTable.myDate < lookup.MaxDate
        AND yourTable.ABC    = 'Y'
    GROUP BY
      lookup.XYZ,
      lookup.MaxDate
  )
    AS lookup
  LEFT JOIN
    yourTable
      ON  yourTable.XYZ    = lookup.XYZ
      AND yourTable.myDate < lookup.MaxDate
      AND yourTable.ABC    = 'Y'
  GROUP BY
    lookup.XYZ,
    lookup.MaxDate
)
  AS lookup
INNER JOIN
  yourTable
    ON  yourTable.XYZ     = lookup.XYZ
    AND yourTable.myDate >= lookup.MaxDate
WHERE
  yourTable.ABC = 'Y'
ORDER BY
  yourTable.comp_id
;


DROP TABLE yourTable;

他のオプションもありますが、それらはすべて少しハッキーです。SOでを検索しgreatest-n-per-group mysqlます。

サンプルデータを使用した私の結果:

Comp_ID | DATE     | XYZ | ABC
------------------------------
   1    | 2012-1-1 | 10  |  Y
   2    | 2011-1-1 | 10  |  Y
   3    | 2006-1-1 | 10  |  Y
   4    | 2011-1-1 | 20  |  Y
   5    | 2002-1-1 | 20  |  Y
   6    | 2000-1-1 | 20  |  Y
于 2012-11-13T18:24:39.713 に答える
0

ここに別の方法があります。うまくいけば、民主党の答えよりも効率的です。
のインデックスでテストします(abc, xyz, date)

SELECT m.xyz, m.date                --- for all columns:    SELECT m.* 
FROM 
    ( SELECT DISTINCT xyz
      FROM  money.cash
      WHERE abc = 'Y'
    ) AS dm
  JOIN
    money.cash AS m
      ON  m.abc = 'Y'
      AND m.xyz = dm.xyz
      AND m.date >= COALESCE(
            ( SELECT im.date
              FROM  money.cash AS im
              WHERE im.abc = 'Y'
                AND im.xyz = dm.xyz
              ORDER BY im.date DESC
                LIMIT 1 
                OFFSET 2                --- to get 3 latest rows per xyz 
            ), DATE('1000-01-01') ) ;

複数の行が同じ(abc, xyz, date)である場合、クエリは 3 つ以上の行を返す場合がありますxyz(3 位に並んでいるすべての行がすべて表示されます)。

于 2012-11-13T19:59:06.767 に答える