Frage

Ich bin die Umsetzung eine kleine Warteschlange zu handhaben, welcher Prozess zuerst ausgeführt wird. Ich verwende eine Tabelle in einer Datenbank, dies zu tun. Hier ist die Struktur der Tabelle (ich spöttisch es in SQLite up):

        "id" INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL ,
        "identifier" VARCHAR NOT NULL ,
        "priority_number" INTEGER DEFAULT 15,
        "timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP,
        "description" VARCHAR

Ich versuche, SQL zu schreiben, mir die Zeile zu geben, von denen Prozess nächsten ausgeführt werden kann. Hier einige Beispieldaten:

id  identifier  priority_number timestamp   description
1   test1   15  2009-01-20 17:14:49 NULL
2   test2   15  2009-01-20 17:14:56 NULL
3   test3   10  2009-01-20 17:15:03 NULL
4   test4   15  2009-01-20 17:15:08 NULL
5   test5   15  2009-01-20 17:32:23 NULL
6   test6   14  2009-01-20 17:32:30 NULL
7   test7   7   2009-01-20 17:32:38 NULL
8   test8   20  2009-01-20 17:32:57 NULL
9   test9   7   2009-01-21 13:47:30 NULL
10  test10  15  2009-01-21 13:50:52 NULL

Wenn ich diese SQL verwende, kann ich die Daten in der richtigen Reihenfolge erhalten:

select * from queue_manager order by priority_number, timestamp;

Das gibt mir das Element mit der niedrigsten Priorität Nummer (am wichtigsten) an der Spitze, und in diesen Prioritätszahlen, die frühestens in die Warteschlange (durch Zeitstempel) an der Spitze.

Ich konnte diese Abfrage ausführen, und nur die erste Zeile nehmen, aber ich würde lieber diese Abfrage mit SQL tun, die mir die einer Zeile des Prozesses geben würde, die (in den Beispieldaten an der Spitze der Warteschlange oben die Reihe mit id = 7).

Ich habe versucht, sich selbst zu tun Joins und Unterabfragen, aber ich muss eine mentale Blockade werden muss -. Ich kann einfach nicht richtig sein, es zu bekommen

Vielen Dank im Voraus!

Bearbeiten

Ich habe vergessen zu erwähnen, dass ich für eine Datenbank-unabhängige Abfrage suchen. Ich spöttischen dies in SQlite, aber es gibt eine gute Möglichkeit, die ich dies in DB2 oder Oracle implementieren wird. Ich hatte gedacht, eine „Grenze 1“ Typ Operator auf meine Anfrage zu verwenden, aber das ist etwas anderes zwischen verschiedenen Datenbank-Engines.

War es hilfreich?

Lösung

Sehen Sie, wenn dies funktioniert:

select * from queue_manager where priority_number = 
(select min(priority_number) from queue_manager) and  
timestamp = (select min(timestamp) 
from queue_manager qm2 
where qm2.priority_number = queue_manager.priority_number)

Andere Tipps

select * from queue_manager order by priority_number, timestamp LIMIT 1;

Wie für eine solche genannte „Datenbank independency“, es ist ein Mythos für die meisten realen Welt Aufgaben. In der Regel können Sie nicht einmal Schema in der Datenbank unabhängig erstellen.

Wenn Sie es wünschen ‚Concurrent sicher‘ zu sein, auf so etwas wie InnoDB tun:

1) Fügen Sie ein 'IN_PROGRESS' Feld.

2) Schalten Sie autoCommit

3) SELECT * FROM queue_manager wo IN_PROGRESS = 0, um durch priority_number, Zeitstempel- LIMIT 1 FOR UDPATE;

4) UPDATE queue_manager IN_PROGRESS SET = 1 wobei id = X;

5) COMMIT

6) die Arbeit machen. Dann löschen Sie die Zeile, wenn seine zur Zufriedenheit erledigt. Haben Sie einen 'Master-Prozess' Griff / redelegate / aufzuräumen alten "IN_PROGRESS Arbeitsplätze.

Der beste Weg, dies zu tun ist, Datenbank abhängig ist; es ist eine viel einfachere Sache im Vergleich zu all den Overhead-Cursor oder andere Konstrukte unterschiedliche Retrieval Procs für die verschiedenen Ziel DBMS zu haben.

Die Auswahl eine begrenzte Anzahl von Zeilen in verschiedenen Geschmacksrichtungen von SQL anders gemacht wird, so dass je nach dem Sie es verwenden könnte ein in Art und Weise aufgebaut sein, es zu tun. Zum Beispiel in MS SQL Server:

SELECT TOP 1
     identifier,
     priority_number,
     timestamp,
     description
FROM
     dbo.Queue_Manager
ORDER BY
     priority_number,
     timestamp

Diese kompatible SQL in ANSI zu tun, sollten die folgenden Methoden arbeiten:

    SELECT
         QM1.identifier,
         QM1.priority_number,
         QM1.timestamp,
         QM1.description
    FROM
         Queue_Manager QM1
    LEFT OUTER JOIN Queue_Manager QM2 ON
         QM2.priority_number < QM1.priority_number OR
         (QM2.priority_number = QM1.priority_number AND QM2.timestamp < QM1.timestamp)
    /* If you're concerned that there might be an exact match by priority_number
and timestamp then you might want to add a bit more to the join */
    WHERE
         QM2.identifier IS NULL

Oder Sie können versuchen:

SELECT
     QM1.identifier,
     QM1.priority_number,
     QM1.timestamp,
     QM1.description
FROM
     Queue_Manager QM1
INNER JOIN
     (
          SELECT
               priority_number
               MIN(timestamp) AS timestamp,
          FROM
               Queue_Manager
          WHERE
               priority_number = 
                    (
                         SELECT
                              MIN(priority_number)
                         FROM
                              Queue_Manager
                    )
          GROUP BY
               priority_number
     ) SQ1 ON
          SQ1.priority_number = QM1.priority_number AND
          SQ1.timestamp = QM1.timestamp

Keine Methode macht exakte Übereinstimmungen in beiden priority_number und Zeitstempel, also, wenn Sie denken, dass das möglich ist (und vielleicht auch wenn Sie es nicht tun) Sie werden eine oder zwei Zeilen hinzufügen müssen eine weitere Ebene zu gehen, um die Kennung verwendet oder etwas anderes, das Einzigartigkeit garantiert. Oder einfach nur Ihre Frontend schreiben den gelegentlichen Fall von immer wieder zwei Reihen (vielleicht einfach ignorieren die zweite - Sie werden es das nächste Mal durchkommen) zu behandeln.

jede Methode testen und sehen, welche für Sie besser funktioniert.

Auch, wie groß erwarten Sie die Warteschlange zu bekommen? Es könnte sinnvoll sein, nur mit Ihrer Bestellung abzufragen BY und hat nur das vordere Ende die erste Zeile abgerufen werden.

Lesen Sie diese Abschnitt und wählen Sie die Variante, die Sie am meisten gibt geeignete Kompatibilität. Wahrscheinlich ist die Verwendung von Cursor die nur mehr oder weniger universell kompatibel Art und Weise, aber eine gewisse Leistungseinbuße hat, die nicht machen könnte es lohnt sich (Profil!).

Relationale Datenbanken sind nicht groß an Warteschlangen verwalten.

Versuchen

bei MSMQ sucht in der Windows-Welt, ActiveMQ in der Java-Welt oder Websphere MQ in der Geschäftswelt.

Diese Produkte machen eine einzige Sache, verwalten Warteschlangen, aber sie tun es auch.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top