2016-02-02 7 views
9

http://sqlfiddle.com/#!9/406cb/2ottenere le righe in base al tempo di scadenza

Ho una tabella libri con categoria 1, 2, 3, 4.

  • Categoria 1 - rimarrà per 1 ora
  • Categoria 2 - sarà soggiorno per 2 ore
  • Categoria 3 - rimarrà per 4 ore
  • Categoria 4 - rimarrà per 6 ore

Come posso scrivere una query per ottenere i risultati desiderati?

Esempio:

  1. se il tempo corrente è 1.454.411,248 mila allora dovrebbe mostrare tutti i libri
  2. se il tempo corrente è 1.454.414,847 mila allora non dovrebbe mostrare categoria 1 libri con unixtime = 1.454.411,248 mila (scadenza dopo un ora)
  3. se l'ora corrente è 1454418448 la categoria - 1, 2, 3, 4 sotto 1, 2, 4, 6 ore di tempo di scadenza non dovrebbe mostrare (unix_time sarà dinamico. Ho usato il valore statico per esempio).

così via ..

Tabella:

CREATE TABLE `books` (
    `id` int(255) NOT NULL AUTO_INCREMENT, 
    `name` longtext NOT NULL, 
    `category` varchar(255) NOT NULL, 
    `unix_time` bigint(20) NOT NULL, 
    `time_data` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=19 ; 


INSERT INTO `books` (`id`, `name`, `category`, `unix_time`, `time_data`) VALUES 
    (1, 'book1', '1', 1454411248, '2016-02-02 05:37:28'), 
    (2, 'book2', '2', 1454411248, '2016-02-02 05:37:28'), 
    (3, 'book3', '3', 1454411248, '2016-02-02 05:37:28'), 
    (4, 'book4', '4', 1454411248, '2016-02-02 05:37:28'), 
    (5, 'book5', '1', 1454411248, '2016-02-02 05:37:28'), 
    (6, 'book6', '2', 1454411248, '2016-02-02 05:37:28'), 
    (7, 'book7', '3', 1454411248, '2016-02-02 05:37:28'), 
    (8, 'book8', '4', 1454411248, '2016-02-02 05:37:28'), 
    (9, 'book9', '1', 1454497648, '2016-02-03 05:37:28'), 
    (10, 'book10', '2', 1454497648, '2016-02-03 05:37:28'), 
    (11, 'book11', '1', 1454497648, '2016-02-03 05:37:28'), 
    (12, 'book12', '2', 1454497648, '2016-02-03 05:37:28'), 
    (13, 'book13', '3', 1454497648, '2016-02-03 05:37:28'), 
    (14, 'book14', '4', 1454497648, '2016-02-03 05:37:28'), 
    (15, 'book15', '1', 1454497648, '2016-02-03 05:37:28'), 
    (16, 'book16', '2', 1454497648, '2016-02-03 05:37:28'), 
    (17, 'book17', '3', 1454497648, '2016-02-03 05:37:28'), 
    (18, 'book18', '4', 1454497648, '2016-02-03 05:37:28'); 

Query:

SELECT *, 
    CASE category 
     WHEN '1' THEN '1454407648' 
     WHEN '2' THEN '1454404048' 
     WHEN '3' THEN '1454396848' 
     WHEN '4' THEN '1454389648' 
    END as category 
from books 
where unix_time >1454411248 
+0

@RyanVincent Ciao Ryan. Ho aggiornato sqlfiddle. Ma la mia domanda è davvero pessima. Proverò ora una query nidificata e aggiornerò di nuovo. – jason

+0

Non viene visualizzato il criterio 2,3,4 – jason

+0

@ hjpotter92 fatto – jason

risposta

4

Prima di tutto, è necessario un tavolo di mettere in relazione le vostre category valori ai vostri duration valori. È possibile creare una tabella fisica oppure utilizzare una sottoquery come questa per generare una tabella virtuale.

select 1 as category, 1 as duration UNION ALL 
    select 2,2 UNION ALL select 3,4 UNION ALL select 4,6 

Questo produce la seguente tabella di ricerca piccola.

|| *category* || *duration* || 
||   1 ||   1 || 
||   2 ||   2 || 
||   3 ||   4 || 
||   4 ||   6 || 

Dopodiché è necessario unire tabella di ricerca che al vostro tavolo books, in questo modo. Questa query può anche includere una colonna expiration, come mostrato.

select b.*, 
     d.duration, 
     FROM_UNIXTIME(unix_time) + INTERVAL d.duration HOUR expiration 
    from books b 
    join (select 1 as category, 1 as duration UNION ALL 
     select 2,2 UNION ALL select 3,4 UNION ALL select 4,6 
     ) d ON b.category = d.category 

Infine, si aggiunge una clausola WHERE per filtrare le righe in corso.

select b.*, 
      d.duration, 
     FROM_UNIXTIME(unix_time) + INTERVAL d.duration HOUR expiration 
    from books b 
    join (select 1 as category, 1 as duration UNION ALL 
     select 2,2 UNION ALL select 3,4 UNION ALL select 4,6 
     ) d ON b.category = d.category 
    where FROM_UNIXTIME(unix_time) + INTERVAL d.duration HOUR >= '2016-02-03 08:00:00' 

In questo esempio ho utilizzato 2016-02-03 08:00:00 come ora corrente. È possibile, in un sistema di produzione, utilizzare NOW().

Si consiglia inoltre di utilizzare una versione sargable della clausola where.

where unix_time >= UNIX_TIMESTAMP('2016-02-03 08:00:00' - INTERVAL d.duration HOUR) 

Infine, si tratta di una preferenza di design, ma la miscelazione DATETIME e unix timestamp colonne è un po 'strano.

+1

@Arth, grazie per la correzione di errore. –

+0

Ciao. In che modo è possibile eseguire test con unixtime anziché "2016-02-03 08:00:00"? Fondamentalmente ho provato ad aggiungere 1454775825 al di fuori della parentesi unix-timestamp ma sto ricevendo un errore. – jason

+0

Ho provato dove unix_time> = 1454775825-UNIX_TIMESTAMP (INTERVAL d.duration HOUR) – jason

2

creare e popolare una tabella di categoria:

  • categoria - id, hours_to_live

Cambio al:

  • libro - id, nome, category_id, unix_time, time_data

e fare riferimento alla tabella categoria con l'estero chiave category_id.

Quindi è possibile ottenere quello che vuoi con un semplice JOIN:

SELECT b.*, 
    FROM books b 
    JOIN category c 
    ON c.id = b.category_id 
WHERE b.unix_time >= NOW() - INTERVAL c.hours_to_live HOUR 
Problemi correlati