2015-04-16 8 views
8

Avere una tabella come questa:Rilevamento modelli in tabella

Table: statuses 
ID | status 
----|--------- 
777 | 1 
675 | 1 
651 | 0 
611 | 1 
600 | 0 
554 | 1 
443 | 0 
323 | 0 
222 | 1 
112 | 1 

come selezionare solo le righe, in cui due (o più) stati in prima fila sono 0? (nel caso campione solo 443, 323) e raggrupparli in base al primo ID in serie.

Così l'output potrebbe essere:

ID | status | group 
----|--------|--------- 
443 | 0  | 443 
323 | 0  | 443 
+0

Può essere programmato in base al linguaggio che si desidera utilizzare? –

+0

SQL non è lo strumento appropriato per questo scopo. Seleziona tutte le righe qualificate, quindi filtra e raggruppale nel codice dell'applicazione. – axiac

+1

come sono ordinati i dati? se non c'è un altro campo che indica l'ordine (quindi fai affidamento sull'ordine di inserimento) non otterrai risultati coerenti. le tabelle sono insiemi, le righe non hanno un ordine intrinseco se non specificato. – 1010

risposta

1
select 
id, STATUS, 
@st_order:=if(@pre_st!=status,0,@st_order+1) as status_order, 
@group_leader:=if(@pre_st!=status,id,@group_leader) as group_leader, 
@pre_st:=status 
from statuses,(select @st_order:=-1, @pre_st:=-1, @group_leader:=-1) val 

Questo sql ti dà l'uscita

id,
stato,
il numero di riga continua stesso status,
leader del gruppo dello stesso stato,
inutile l colonna ast

Dato l'input, la prima uscita quattro colonne è

ID | stato | numero di riga di stato | capogruppo stato
777 | 1 | 0 | 777
675 | 1 | 1 | 777
651 | 0 | 0 | 651
611 | 1 | 0 | 611
600 | 0 | 0 | 600
554 | 1 | 0 | 554
443 | 0 | 0 | 443
323 | 0 | 1 | 443
222 | 1 | 0 | 222
112 | 1 | 1 | 222

Così puoi fare quello che vuoi in una selezione esterna.

+0

vedere [this] (http://stackoverflow.com/questions/16715504/mysql-define-a-variable-within-select-and-use-it-within-the-same-select/16715618#16715618). l'ordine in cui vengono valutati molteplici usi di una variabile in una query non è garantito. – 1010

1

È possibile raggiungere questo obiettivo utilizzando po 'di logica utilizzando query sub

set @cnt=0; 
set @id=-1; 
SELECT 
    t3.id, t3.status, t3.dup_id AS `group` 
FROM 
    (SELECT 
     id, 
      status, 
      IF(status = 0, @cnt:[email protected] + 1, @cnt:=0) AS great, 
      IF(@cnt = 1, @id:=id, IF(status = 0, @id, - 1)) AS dup_id 
    FROM 
     statuses) t3 
WHERE 
    t3.dup_id IN (SELECT 
      t1.dup_id 
     FROM 
      (SELECT 
       id, 
        status, 
        IF(status = 0, @cnt:[email protected] + 1, @cnt:=0) AS great, 
        IF(@cnt = 1, @id:=id, IF(status = 0, @id, - 1)) AS dup_id 
      FROM 
       statuses) t1 
     GROUP BY t1.dup_id 
     HAVING COUNT(t1.dup_id) > 1 
      AND t1.dup_id != - 1); 

risultato sarà come vi aspettavate

id | status | group 
----|--------|--------- 
443 | 0  | 443 
323 | 0  | 443 
+0

troppo lungo, complicato, prova ancora una volta, ma in un modo semplice. –

2

Se un approccio programmatico non è possibile, si può provare questa query (anche se avrà prestazioni peggiori).

select 
    s.id, 
    0 as status, 
    group_field.id as group 
from 
    statuses s, 
    (select id from statuses where status = 0 group by id having count(1) > 1 limit 1) group_field 
where 
    s.id in(select id from statuses where id = 0 group by id having count(1) > 1)