2015-05-20 15 views
6

Ci sono due tipi di risultati che voglio tornare:query SQL per selezionare minimo di 10 risultati

  • notifiche non letti
  • leggere le notifiche

Se ci sono> 10 notifiche non lette disponibili I vuoi selezionare quanti ce ne sono

Se ci sono < = 10, voglio selezionare tutti (diciamo che c'erano 7) le notifiche non lette e 3 'filler' leggere no tifications. Come posso realizzare questo?

Se avessi voluto selezionare solo tutte le notifiche non lette mia domanda sarebbe:

SELECT * FROM notifications WHERE read = 0 

Se avessi voluto selezionare solo tutte le notifiche letto la mia domanda sarebbe:

SELECT * FROM notifications WHERE read = 1 

risposta

5

Questo dovrebbe aiutare a: http://sqlfiddle.com/#!9/e7e2a/2

SELECT * FROM 
(
    SELECT @rownum := @rownum + 1 AS rownum, name, read 
    FROM notifications, 
    (SELECT @rownum := 0) r --initialise @rownum to 0 
) t 
WHERE read = 0 OR (read = 1 AND rownum <= 10) 
ORDER BY rownum 

I record sono numerati con @rownum. La clausola where si assicura che la lettura = 0 sia selezionata per prima. Se sono fino a 10 o più, tutti sono selezionati. In caso contrario, viene verificato il secondo criterio (read = 1 AND rownum <= 10).

(SELECT @rownum := 0) r inizializza @rownum a 0 altrimenti sarebbe NULL e NULL+1=NULL

enter image description here

+0

Puoi spiegare cosa sta succedendo qui a piccolo? In particolare r <= 10 e (SELECT @rownum: = 0) r – maxhud

+0

Grazie per la spiegazione! Bella risposta. – maxhud

+0

Tutte le righe sono numerate, a partire dal non letto fino alla lettura. Se non letto> = 10, vengono selezionati tutti i non letti. Se non letto <10, la numerazione continua nelle righe lette, ma vogliamo solo le righe numerate <= 10 – codingbiz

5

cosa si può fare è unione i due risultati, ordine per la più importante, e quindi limitare l'Unione:

SELECT Col1, Col2, ... 
FROM 
(
    SELECT Col1, Col2, `read`, ... FROM notifications WHERE read = 0 
    UNION 
    SELECT Col1, Col2, `read`, ... FROM notifications WHERE read = 1 
) x 
ORDER BY x.`read` -- And probably a column like Time? 
LIMIT 10; 

SqlFiddle here

Edit, Re: Deve restituire tutto da leggere, non solo prima 10

Scuse, ho perso quella parte della domanda. Non riesco a pensare ad un modo elegante per raggiungere questo obiettivo, quindi ecco una ~ soluzione parziale che ricorre a una procedura imperativa e una tabella temporanea per riempire le righe, se necessario: usa la soluzione codingbiz finché MySql non supporta le funzioni di Windowing (ad es. ROW_NUMBER() OVER (PARTITION BY read ORDER BY Col1 DESC)

+4

non Sarà questo soltanto il ritorno 10 risultati se ci sono 15 notifiche non lette? – maxhud

+0

Sì, non è giusto. Se lo fosse, potrebbe essere scritto molto più semplicemente. – Strawberry

+0

Sì, buoni punti entrambi - [Strawberry] (http://sqlfiddle.com/#!9/494df/4) e ancora funzionante sul problema ALL o Max10. Non riesco comunque a vedere una soluzione non imperativa :( – StuartLC

0

Se la tabella non arriva a grandi si potrebbe provare unirsi a loro nel modo seguente

SELECT *, 
    ROW_NUMBER() OVER (
     ORDER BY read 
    ) AS RowNum 
FROM (
    SELECT * FROM notifications WHERE read = 0 
    UNION 
    SELECT * FROM notifications WHERE read = 1 

) T1 
WHERE T1.read = 0 OR (T1.read = 1 AND T1.RowNum <= 10) 
ORDER BY T1.read DESC 

Quando queste tabelle fanno diventare grandi, si potrebbe tentare di eseguire un conteggio sul tavolo 'leggere' prima e vedere se ha più di 10 messaggi non letti e in base a tale risultato seleziona i messaggi letti o non letti

INT @readMessages = SELECT COUNT(*) FROM notifications WHERE read = 0 

SELECT CASE 
    WHEN @readMessages > 10 THEN SELECT * FROM notifications WHERE read = 0 
    ELSE (
     SELECT * FROM notifications WHERE read = 0 
     UNION 
     SELECT * FROM notifications WHERE read = 1 LIMIT 0, [email protected] 
    ) 

Non so se è tutta la sintassi MySQL corretta (più un ragazzo SQL), ma forse ti aiuta.

+2

No' ROW_NUMBER() 'su MySQL – sqluser

+0

ha trovato questo: http://blog.sqlauthority.com/ 2014/03/08/mysql-generation-row-number-for-each-row-using-variable/ SET \ @row_number: = 0; SELECT *, \ @row_number: = \ @ row_number + 1 AS ROWNUM DA ( SELECT * FROM WHERE notifiche leggere = 0 UNION SELECT * FROM WHERE notifiche leggere = 1 ) T1 WHERE T1.read = 0 OR (T1.read = 1 AND T1.RowNum <= 10) ORDINA DA T1.read DESC Ci scusiamo per \ @, ma pensa che sto facendo riferimento a un utente – Rik

-1

Si prega di verificare questa soluzione.

SELECT * FROM `notifications` WHERE `read`=1 OR `read`=0 ORDER BY `read` LIMIT 10 

http://sqlfiddle.com/#!9/c72af/1

Problemi correlati