присваивать одинаковый ранг строке с тем же свойством в MySQL

0

Я использую следующий запрос для извлечения случайной строки из тех, у которых минимальная разница в дате в подгруппе (как определено парами ID1, ID2).

Он не работает, так как шаги, которые ранжируют строки по разнице дат, присваивают rank = 1 только первому наблюдению (т.е. даже если второе имеет ту же разницу в дате и должно получить ранг = 1 тоже).

Как-то мне нужно изменить предложение WHEN на что-то вроде...

 CASE 
 WHEN @id1 = t.id1 AND @id2 = t.id2 AND @diff != diff THEN @rownum := @rownum + 1
 ELSE @rownum := 1

но когда я это делаю, он не находит поле diff...

DROP TABLE IF EXISTS temp4;
    CREATE TABLE temp4 AS
    SELECT x.id1,
           x.id2,
           x.YEAR,
           x.MMDD,
           x.id3,
           x.id3_YEAR,
           x.id3_MMDD,
           x.rk
     FROM (SELECT t.*,
                   ABS(DATEDIFF(CONCAT(CAST(t.id3_YEAR AS CHAR(4)),'-', LEFT(t.id3_MMDD,2),'-',RIGHT(t.id3_MMDD,2)),
                            CONCAT(CAST(t.YEAR AS CHAR(4)),'-', LEFT(t.MMDD,2),'-',RIGHT(t.MMDD,2))))  AS diff,
                   CASE 
                     WHEN @id1 = t.id1 AND @id2 = t.id2 THEN @rownum := @rownum + 1
                     ELSE @rownum := 1
                   END AS rk,
                   @id1 := t.id1,
                   @id2 := t.id2
              FROM temp3 t
              JOIN (SELECT @rownum := 0, @id1  := 0, @id2 := 0) r
          ORDER BY t.id1, t.id2, diff, RAND()) x;

Я вставляю дамп SQL

DROP TABLE IF EXISTS `temp3`;
CREATE TABLE IF NOT EXISTS `temp3` (
  `id1` char(7) NOT NULL,
  `id2` char(7) NOT NULL,
  `YEAR` year(4) NOT NULL,
  `MMDD` char(4) NOT NULL,
  `id3` char(7) NOT NULL,
  `id3_YEAR` year(4) NOT NULL,
  `id3_MMDD` char(4) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


INSERT INTO `temp3` VALUES('1', '2', 1992, '0107', '55', 1991, '0528');
INSERT INTO `temp3` VALUES('1', '2', 1992, '0107', '57', 1991, '0701');
INSERT INTO `temp3` VALUES('1', '3', 1992, '0107', '88', 2000, '0101');
INSERT INTO `temp3` VALUES('1', '3', 1992, '0107', '44', 2000, '0101');

Эта версия действительно очень близка к тому, что мне нужно

DROP TABLE IF EXISTS temp4;
CREATE TABLE temp4 AS
SELECT
    x.id1,
    x.id2,
    x.YEAR,
    x.MMDD,
    x.id3,
    x.id3_YEAR,
    x.id3_MMDD
FROM
(   SELECT
        t.*,
        @rownum := CASE 
            WHEN @id1 = t.id1 AND @id2 = t.id2 AND @diff != diff THEN @rownum + 1

            ELSE 1
            END AS rk,
        @id1 := t.id1,
        @id2 := t.id2,
        @diff := t.diff
    FROM
    (   SELECT
            t.*,
             ABS(DATEDIFF(CONCAT(CAST(t.id3_YEAR AS CHAR(4)),'-', LEFT(t.id3_MMDD,2),'-',RIGHT(t.id3_MMDD,2)),
             CONCAT(CAST(t.YEAR AS CHAR(4)),'-', LEFT(t.MMDD,2),'-',RIGHT(t.MMDD,2)))) AS diff
        FROM temp3 t
        ORDER BY t.id1, t.id2, diff, RAND()
    ) t,
    (   SELECT @rownum := 0, @id1 := null, @id2 := null, @diff := null ) r
) x
WHERE x.rk = 1;
  • 0
    @ omg-ponies @OMGPonies Я думаю, что решение заключается в правильном ранжировании также строк, которые имеют одинаковую разницу, но не читаются как первые строки (то есть они также должны получить RANK = 1!). Я пробовал CASE WHEN @ id1 = t.id1 AND @ id2 = t.id2 AND @diff! = Diff THEN @rownum: = @rownum + 1 ELSE @rownum: = 1
  • 0
    Вы хотите вернуть одну строку - какое это имеет значение, если вы ранжируете связи, а затем случайным образом делегируете первое или однозначное ранжирование в первую очередь? Для сравнения, ваш подход неоправданно сложен.
Показать ещё 6 комментариев
Теги:

1 ответ

0

Это рабочее решение. Спасибо @OMG Ponies за вашу помощь.

SELECT
 x.id1,
 x.id2,
 x.YEAR,
 x.MMDD,
 x.id3,
 x.id3_YEAR,
 x.id3_MMDD
FROM
( SELECT
  t.*,
  @rownum := CASE 
   WHEN @id1 = t.id1 AND @id2 = t.id2 THEN @rownum + 1
   ELSE 1
   END AS rk,
  @id1 := t.id1,
  @id2 := t.id2
 FROM
 ( SELECT
   t.*,
    ABS(DATEDIFF(CONCAT(CAST(t.id3_YEAR AS CHAR(4)),'-', LEFT(t.id3_MMDD,2),'-',RIGHT(t.id3_MMDD,2)),
    CONCAT(CAST(t.YEAR AS CHAR(4)),'-', LEFT(t.MMDD,2),'-',RIGHT(t.MMDD,2)))) AS diff
  FROM temp3 t
  ORDER BY t.id1, t.id2, diff, RAND()
 ) t,
 ( SELECT @rownum := 0, @id1 := null, @id2 := null ) r
) x
WHERE x.rk = 1;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню