2016-02-02 10 views
9

http://sqlfiddle.com/#!9/406cb/2Reihen erhalten basierend auf Ablaufzeit

ich eine Tabelle Bücher mit Kategorie haben 1, 2, 3, 4.

  • Kategorie 1 - wird für 1 Stunde Aufenthalt
  • Kategorie 2 - wird Aufenthalt für 2 Stunden
  • Kategorie 3 - bleiben 4 Stunden für
  • Kategorie 4 - bleiben für 6 Stunden

Wie kann ich eine Abfrage schreiben, um die gewünschten Ergebnisse zu erhalten?

ZB:

  1. wenn aktuelle Zeit 1454411248 dann soll es
  2. alle Bücher zeigen, wenn die aktuelle Zeit ist 1454414847, dann sollte es nicht nach einer Stunde mit Unix-Zeit = 1454411248 (Ablauf der Kategorie 1 Bücher zeigen)
  3. Wenn die aktuelle Zeit 1454418448 ist, sollte die Kategorie - 1, 2, 3, 4 unter 1, 2, 4, 6 Stunden Ablaufzeit nicht angezeigt werden (unix_time wird dynamisch sein. Ich habe statischen Wert zum Beispiel verwendet).

so weiter ..

Tabelle:

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'); 

Abfrage:

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 Hallo Ryan. Ich habe Update sqlfiddle. Aber meine Frage ist wirklich schlecht. Ich werde jetzt eine verschachtelte Abfrage versuchen und erneut aktualisieren. – jason

+0

Es zeigt keine Kategorie 2,3,4 – jason

+0

@ hjpotter92 done – jason

Antwort

4

Zunächst einmal müssen Sie eine Tabelle Ihre category Werte auf Ihre duration Werte beziehen. Sie könnten eine physische Tabelle erstellen oder eine Unterabfrage wie diese verwenden, um eine virtuelle Tabelle zu generieren.

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

Dies erzeugt die folgende kleine Nachschlagetabelle.

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

Als nächstes müssen Sie Ihre books Tabelle, die Lookup-Tabelle verbinden, wie so. Diese Abfrage kann auch eine Spalte expiration enthalten, wie gezeigt.

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 

Schließlich fügen Sie eine WHERE Klausel, die nicht abgelaufene Reihen heraus zu filtern.

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 diesem Beispiel verwendete ich 2016-02-03 08:00:00 als die aktuelle Zeit. Sie könnten in einem Produktionssystem NOW() verwenden.

Sie würden auch klug sein, eine sargable Version der where Klausel zu verwenden.

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

Schließlich ist dies ein Design bevorzugt, aber das Mischen DATETIME und Unix-Zeitstempel Spalten ist ein wenig seltsam.

+1

@Arth, danke für den Tippfehler. –

+0

Hallo. Wie kann mit unixtime statt '2016-02-03 08:00:00' getestet werden? Im Grunde habe ich versucht, 1454775825 außerhalb der Unix-Timestamp-Klammer hinzuzufügen, aber ich bekomme einen Fehler. – jason

+0

Ich habe versucht, wo unix_time> = 1454775825-UNIX_TIMESTAMP (INTERVAL d.duration HOUR) – jason

2

erstellen und Kategorie-Tabelle füllen:

  • Kategorie - id, hours_to_live

ändern Buch:

  • Buch - id, name, category_id, unix_time, time_data

und Referenz der Kategorie Tabelle mit dem Fremd Schlüssel Kategorie_ID.

Anschließend können Sie erreichen, was Sie mit einem einfachen wollen 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 
Verwandte Themen