2015-08-19 14 views
7

Ho bisogno di 2 id per ogni gruppo.MYSQL Gruppo per colonna con 2 righe per ciascun gruppo

SELECT `id`, `category`.`cat_name` 
FROM `info` 
LEFT JOIN `category` ON `info`.`cat_id` = `category`.`cat_id` 
WHERE `category`.`cat_name` IS NOT NULL 
GROUP BY `category`.`cat_name` 
ORDER BY `category`.`cat_name` ASC 

Come fare?

dati di esempio:

id cat_name 
1 Cat-1 
2 Cat-1 
3 Cat-2 
4 Cat-1 
5 Cat-2 
6 Cat-1 
7 Cat-2 

uscita sarà:

id cat_name 
6 Cat-1 
4 Cat-1 
7 Cat-2 
5 Cat-2 
+0

Si prega di fornire i dati del campione e risultato desiderato. – RubahMalam

+0

'SELEZIONARE GROUP_CONCAT (info.id), GROUP_CONCAT (category.id), ...' – raina77ow

+0

Quale "2 righe" vuoi? Qualsiasi due file? Le due righe con gli ID più alti, che sembra essere ciò che mostra il tuo output? –

risposta

3

Se avete bisogno di due ID arbitrarie, quindi utilizzare min() e max():

SELECT c.`cat_name` , min(id), max(id) 
FROM `info` i INNER JOIN 
    `category` c 
    ON i.`cat_id` = c.`cat_id` 
WHERE c.`cat_name` IS NOT NULL 
GROUP BY c`.`cat_name` 
ORDER BY c.`cat_name` ASC ; 

Nota: Si utilizza a LEFT JOIN e quindi aggregando per una colonna nel seconda tabella. Di solito non è una buona idea, perché le non-partite sono tutte collocate in un gruppo NULL. Inoltre, la tua clausola WHERE trasforma lo LEFT JOIN in uno INNER JOIN, quindi l'ho risolto. La clausola WHERE potrebbe essere o meno necessaria, a seconda che lo cat_name sia o meno NULL.

Se si desidera che i due più grandi o più piccoli - e può sopportare di averli nella stessa colonna:

SELECT c.`cat_name`, 
     substring_index(group_concat id order by id), ',', 2) as ids_2 
FROM `info` i INNER JOIN 
    `category` c 
    ON i.`cat_id` = c.`cat_id` 
WHERE c.`cat_name` IS NOT NULL 
GROUP BY c`.`cat_name` 
ORDER BY c.`cat_name` ASC ; 
0
SELECT id, cat_name 
    FROM 
     (SELECT @prev := '', @n := 0) init 
    JOIN 
     (SELECT @n := if(c.cat_name != @prev, 1, @n + 1) AS n, 
       @prev := c.cat_name, 
       c.cat_name, 
       i.id 
      FROM `info` 
      LEFT JOIN `category` ON i.`cat_id` = c.`cat_id` 
      ORDER BY c.cat_name ASC, i.id DESC 
    ) x 
    WHERE n <= 2 
    ORDER BY cat_name ASC, id DESC; 

More discussion in Group-wise-max blog.

0

In un database che ha sostenuto le funzioni delle finestre, si potrebbe enumerare la posizione di ciascun record in ogni gruppo (ROW_NUMBER() OVER (partizione DA CAT_NAME ORDER BY id DESC)) e quindi selezionare i record in posizione relativa 1 o 2.

In MySQL, si può imitare questo da un self-join che conta il numero di record il cui id è maggiore di o uguale a un record dello stesso cat_name (partizione ... ORDER bY id DESC). Il record n. 1 in un gruppo cat_name ha un solo record di> = il suo id e il numero di registrazione N ha N tali record.

Questa query

SELECT id, cat_name 
    FROM ( SELECT c.id, c.cat_name, COUNT(1) AS relative_position_in_group 
       FROM category c 
     LEFT JOIN category others 
       ON c.cat_name = others.cat_name 
        AND 
        c.id <= others.id 
      GROUP BY 1, 2) d 
    WHERE relative_position_in_group <= 2 
ORDER BY cat_name, id DESC; 

produce:

+----+----------+ 
| id | cat_name | 
+----+----------+ 
| 6 | Cat-1 | 
| 4 | Cat-1 | 
| 7 | Cat-2 | 
| 5 | Cat-2 | 
+----+----------+ 
0

Vostri criteri è come Select id, cat_name from mytable group by cat_name quindi aggiornarla a Select SELECT SUBSTRING_INDEX(group_concat(id), ',', 2), cat_name from mytable group by cat_name e si otterrà un output simile a quanto segue

id cat_name 
1,2 Cat-1 
3,5 Cat-2 

Does aiuta ?

0

l'unica cosa che serve è l'aggiunta limit option alla fine della query e ordering in descending ordine come illustrato di seguito:

SELECT `id`, `category`.`cat_name` 
FROM `info` 
LEFT JOIN `category` ON `info`.`cat_id` = `category`.`cat_id` 
WHERE `category`.`cat_name` IS NOT NULL 
GROUP BY `category`.`cat_name` 
ORDER BY `category`.`cat_name` DESC 
LIMIT 2 
+0

Non penso che funzionerebbe. Ciò limiterà i risultati finali a 2, non in base al gruppo. – Sebas

0

Molto semplice Raggruppa per ID.si tratta di dati duplicati di gruppo

0

Ho una domanda scritta per voi. Spero che risolverà il problema:

SELECT 
    id, cat_name 
FROM 
    (SELECT 
     *, 
      @prevcat, 
      CASE 
       WHEN cat_name != @prevcat THEN @rownum:=0 
      END, 
      @rownum:[email protected] + 1 AS cnt, 
      @prevcat:=cat_name 
    FROM 
     category 
    CROSS JOIN (SELECT @rownum:=0, @prevcat:='') r 
    ORDER BY cat_name ASC , id DESC) AS t 
WHERE 
    t.cnt <= 2; 
+0

@ Chayan, questo funziona per voi? –

+0

@Chayan, selezionalo come risposta se lo trovi adatto alla soluzione del tuo problema –

0

Meglio usare la funzione rango la query di esempio riportato di seguito per il vostro output sarà utile a controllare

select a.* from 
(
select a, b ,rank() over(partition by b order by a desc) as rank 
from a 
group by b,a) a 

where rank<=2 
0

si prega di provare questo, ha funzionato nei dati del campione indicata

SELECT `id`, `category`.`cat_name` 
FROM `info` 
LEFT JOIN `category` ON `info`.`cat_id` = `category`.`cat_id` 
WHERE `category`.`cat_name` IS NOT NULL and (SELECT count(*) 
FROM info t 
WHERE t.id>=info.id and t.cat_id=category.cat_id)<3 

GROUP BY `category`.`cat_name`,id 
ORDER BY `category`.`cat_name` ASC 
0

Beh, è ​​piuttosto brutto, ma sembra che funzioni.

select 
cat_name, 
max(id) as maxid 
from 
table1 
group by cat_name 
union all 
select 
cat_name, 
max(id) as maxid 
from 
table1 
where not exists 
(select 
    cat_name, 
    maxid 
    from 
    (select cat_name,max(id) as maxid from table1 group by cat_name) t 
    where t.cat_name = table1.cat_name and t.maxid = table1.id) 
group by cat_name 
order by cat_name 

SQLFiddle

In sostanza, ci vuole il massimo per ogni CAT_NAME, e poi sindacati che a una seconda query che esclude la massima id effettivo per ogni CAT_NAME, che consente di ottenere il secondo più grande id per ogni . Speriamo che tutto ciò che aveva un senso ...

0
select id, cat_name from 

(
select @rank:=if(@prev_cat=cat_name,@rank+1,1) as rank, 
     id,cat_name,@prev_cat:=cat_name 
from Table1,(select @rank:=0, @prev_cat:="")t 
    order by cat_name, id desc 
) temp 

where temp.rank<=2 

Si possono verificare risultato al http://sqlfiddle.com/#!9/acd1b/7

Problemi correlati