2009-02-26 12 views
33

Ich muss eine SELECT-Anweisung finden, die entweder einen Datensatz zurückgibt, der genau mit meiner Eingabe übereinstimmt, oder die nächste Übereinstimmung, wenn keine exakte Übereinstimmung gefunden wird.Den nächsten numerischen Wert in der Datenbank finden

Hier ist meine Select-Anweisung so weit.

SELECT * FROM [myTable] 
WHERE Name = 'Test' AND Size = 2 AND PType = 'p' 
ORDER BY Area DESC 

Was ich tun muß, ist die größte Übereinstimmung mit dem ‚Area‘ Feld zu finden, so dass, wenn meine Eingabe 1,125 ist und die Datenbank enthält 2, 1,5, 1 und 0,5 die Abfrage den Datensatz mit 1 zurückkehren

Meine SQL-Kenntnisse sind sehr begrenzt, so dass jede Hilfe geschätzt werden würde.

Antwort

56

die Differenz zwischen dem Gebiet und Ihrer Eingabe erhalten, so dass immer positive absoluten Wert nehmen, dann aufsteigend sortieren und nimmt die erste

SELECT TOP 1 * FROM [myTable] 
WHERE Name = 'Test' and Size = 2 and PType = 'p' 
ORDER BY ABS(Area - @input) 
2

Wie sei es durch die Differenz zwischen dem Eingang der Bestellung und [Bereich] wie zum Beispiel:

DECLARE @InputValue DECIMAL(7, 3) 

SET @InputValue = 1.125 

SELECT TOP 1 * FROM [myTable] 
WHERE Name = 'Test' AND Size = 2 AND PType = 'p' 
ORDER BY ABS(@InputValue - Area) 
0

Bei der Verwendung von MySQL

SELECT * FROM [myTable] ... ORDER BY ABS(Area - SuppliedValue) LIMIT 1 
7

etwas schreckliches, in Analogie zu:

ORDER BY ABS(Area - 1.125) ASC LIMIT 1 

Vielleicht?

2
SELECT * 
    FROM [myTable] 
    WHERE Name = 'Test' AND Size = 2 AND PType = 'p' 
    ORDER BY ABS(Area - 1.125) 
    LIMIT 1 

- MarkusQ

1

Beachten Sie, dass obwohl ABS() durch so ziemlich alles unterstützt wird, ist es technisch nicht Standard ist (in SQL99 zumindest). Wenn Sie aus irgendeinem Grund ANSI-Standard SQL schreiben müssen, dann würden Sie haben, um das Problem mit einem CASE-Operator arbeiten:

SELECT * FROM myTable 
WHERE Name='Test' AND Size=2 AND PType='p' 
ORDER BY CASE Area>1.125 WHEN 1 THEN Area-1.125 ELSE 1.125-Area END 
2

Wenn Sie viele Zeilen, die die Gleichheit erfüllen auf Name Prädikate, Size und PType Spalten Dann möchten Sie möglicherweise Bereichsprädikate in die Spalte Area in Ihrer Abfrage einschließen. Wenn die Spalte Area indiziert ist, kann dies einen effizienten indexbasierten Zugriff ermöglichen.

Die folgende Abfrage (geschrieben mit Oracle-Syntax) verwendet einen Zweig eines UNION ALL den Datensatz zu finden, mit minimalen Area >= Ihr Ziel, während der andere Zweig den Datensatz mit maximal Area < Ihr Ziel findet. Einer dieser beiden Datensätze wird der Datensatz sein, nach dem Sie suchen. Dann können Sie ORDER BY ABS(Area - ?input) den Gewinner aus diesen beiden Kandidaten auswählen. Leider ist die Abfrage aufgrund verschachtelter SELECTS, die zum Erzwingen der gewünschten ROWNUM/ORDER BY-Priorität benötigt werden, komplex.

SELECT * 
FROM 
    (SELECT * FROM 
    (SELECT * FROM 
     (SELECT * FROM [myTable] 
     WHERE Name = 'Test' AND Size = 2 AND PType = 'p' AND Area >= ?target 
     ORDER BY Area) 
     WHERE ROWNUM < 2 
    UNION ALL 
    SELECT * FROM 
     (SELECT * FROM [myTable] 
     WHERE Name = 'Test' AND Size = 2 AND PType = 'p' AND Area < ?target 
     ORDER BY Area DESC) 
     WHERE ROWNUM < 2) 
    ORDER BY ABS(Area - ?target)) 
WHERE rownum < 2 

ein guter Index für diese Abfrage wäre (Name, Size, PType, Area), in welchem ​​Fall der Abfrageausführung zu erwarten Plan auf zwei Indexbereich Scans basieren würde, die jeweils eine einzelne Zeile zurückgegeben.

-2

Wählen Sie die min, wo [field]> your_target_value den max Wählen wo [field] < your_target_value

+1

Willkommen bei SO und Dank für den Versuch zu tragen! Aber es gibt einige Dinge in Ihrer Antwort zu verbessern, um nützlich zu sein.Erstens ist das Markup gebrochen. Codeblöcke sollten um 4 Leerzeichen eingerückt sein, siehe [Hilfe bearbeiten] (http://stackoverflow.com/editing-help). Abgesehen davon wäre eine Erklärung nützlich, da Code-only-Antworten im Allgemeinen schwer zu verstehen sind. Zu sagen, dass Ihre Antwort SQL-Pseudocode ist oder sie in reguläres SQL umschreiben, wäre auch schön. Dennoch ist Ihre Antwort nützlich und nach dem Ausarbeiten der Probleme kann es aufgewertet werden. – Palec

Verwandte Themen