2010-09-26 6 views
0

J'utilise la requête suivante pour extraire une ligne aléatoire de celles ayant la différence de date minimum dans un sous-groupe (tel que défini par une paire ID1, ID2). Cela ne fonctionne pas, car les étapes qui classent les lignes par différence de date attribuent rank = 1 uniquement à la première observation (c'est-à-dire même si la seconde a la même différence de date et reçoit un rang = 1).attribue le même rang à la ligne avec la même propriété dans mysql

D'une certaine manière je dois changer la clause WHEN à quelque chose comme ...

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

mais quand je le fais, il ne trouve pas le champ 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; 

Je m coller le dump 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'); 

Cette version est en fait très proche de ce que je dois

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-poneys @OMGPonies Je pense que la solution réside dans le classement aussi correctement les lignes qui ont la même diff mais lisent pas comme premières lignes (à savoir qu'ils devraient obtenir RANK = 1 aussi!). J'ai essayé CAS QUAND @ id1 = t.id1 ET @ id2 = t.id2 ET @diff! = Diff ALORS @rownum: = @rownum + 1 ELSE @rownum: = 1 – Cat

+0

Vous voulez retourner une seule ligne - Qu'est-ce que cela a d'important si vous classifiez les liens et ensuite déléguez aléatoirement le premier vs le classement unique en premier lieu? En comparaison, votre approche est inutilement complexe. –

+0

Parmi ceux qui ont la différence de date minimum, je dois en choisir un à chaque fois. Dans l'exemple ci-dessus, ID3 = 88 et ID3 = 44 devraient avoir la même chance d'apparaître dans la table des résultats, alors que ID3 = 55 ne devrait jamais apparaître, parce que dans son groupe (ID1 = 1, ID2 = 2) il a une date plus élevée différence que ID3 = 57. Ton aide est grandement appréciée! @OMGPonies – Cat

Répondre

0

Ceci est une solution de travail. Merci @OMG Ponies pour votre aide.

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; 
Questions connexes