SQL Überprüfung auf NULL und incrementals
Frage
Ich möchte überprüfen, ob es etwas eine Reihe Rückgabe gegeben ist gegen zu prüfen, und wenn diese Abfrage keine Einträge zurückgibt, erhöhen Sie die Zahl bis ein Eintrag erreicht ist, und dass der Eintritt anzuzeigen. Derzeit sieht der Code wie folgt aus:
SELECT *
FROM news
WHERE DATEDIFF(day, date, getdate() ) <= #url.d#
ORDER BY date desc
wobei # url.d # ist eine ganze Zahl (zB 31) durchlaufen wird. Wenn das keine Ergebnisse, würde Ich mag die Zahl in # url.d # 1 von gespeichert zu erhöhen, bis ein Eintrag gefunden wird.
Lösung
Diese Art von inkrementeller Abfrage ist einfach nicht effizient. Sie werden bessere Ergebnisse erzielen, indem er sagte - „Ich werde nie mehr als 100 Ergebnisse brauchen mich so geben diese“:
SELECT top 100 *
FROM news
ORDER BY date desc
Filterung Dann weiter auf der Client-Seite, wenn Sie einen bestimmten Tages Artikel (wie die Einzelteile mit einem gemeinsamen Datum als erstes Element im Ergebnis) wollen.
Oder könnten Sie Ihre mehr Abfrage-Anforderung in eine zwei Abfrageanforderung umwandeln:
DECLARE
@theDate datetime,
@theDate2 datetime
SET @theDate = (SELECT Max(date) FROM news)
--trim the time off of @theDate
SET @theDate = DateAdd(dd, DateDiff(dd, 0, @theDate), 0)
SET @theDate2 = DateAdd(dd, 1, @theDate)
SELECT *
FROM news
WHERE @theDate <= date AND date < @theDate2
ORDER BY date desc
Andere Tipps
In MySQL
:
SELECT news.*,
(
SELECT COUNT(*)
FROM news
WHERE date < DATEADD(day, GETDATE(), -#url.d#)
)
FROM news
WHERE date >= DATEADD(day, GETDATE(), -#url.d#)
ORDER BY
date DESC
LIMIT 1
In SQL Server
:
SELECT TOP 1
news.*,
(
SELECT COUNT(*)
FROM news
WHERE date < DATEADD(day, GETDATE(), -#url.d#)
)
FROM news
WHERE date >= DATEADD(day, GETDATE(), -#url.d#)
ORDER BY
date DESC
Beachten Sie, dass diese Syntax macht Ihre Abfrage sargable , also kann ein Index effizient zu filtern, auf date
verwendet werden.
Erstens glaube ich, dass Sie wahrscheinlich für die Verwendung DateDiff-Funktion in Ihrer where-Klausel avpod wollen, stattdessen berechnen den Stichtag gewünscht und alle Berechnungen auf der Datumsspalte verwenden Sie in der Where-Klausel, wird dies effizienter sein, so anstatt
WHERE DATEDIFF(day, date, getdate() ) <= #url.d#
Sie würde so etwas haben
WHERE date >= @cutoffDate
Dabei galt @cutoffDate ist ein berechnetes Datum basierend auf # url.d #
Jetzt, da für den richtigen Stichtag greifen. Meine Vermutung ist, dass unter normalen Umständen wird es Artikel aus der Anfrage zurückgegeben werden sonst würden Sie nur Artikel aus dem jüngsten Datum greifen. So ist der Ansatz, den ich würde wäre die ÄLTESTE des berechneten Stichtag zu greifen (basierend auf # # url.d und der letzte Artikel Datum. So etwas wie
-- @urld == #url.d
-- compute the cutoff date as the OLDEST of the most recent article and
-- the date based on #url.d
declare @cutoff datetime
select @cutoff = DateAdd(dd,-1*@urld,GetDate())
select @cutoff
select @cutoff = min(cutoffDate)
from
(SELECT Max(date) as cutoffDate from News
UNION
select @cutoff) Cutoff
-- grab the articles with dates that are more recent than the cutoff date
select *
from News
WHERE date >= @cutoff
Ich vermute auch, dass Sie würde wahrscheinlich für die Tage bis Mitternacht runden möchten (die ich hier nicht tat). Dies ist ein Multi-Abfrage Ansatz und soll wahrscheinlich in einer einzigen gespeicherten Prozedur implementiert wird ... wenn dies ist, was Sie suchen.
Viel Glück mit dem Projekt!
Wenn Sie die eine Zeile gesucht:
SELECT t.*
FROM NEWS t
WHERE t.id = (SELECT MAX(n.id)
FROM NEWS n
WHERE n.date BETWEEN DATEADD(day, -:url.d, getDate()) AND getDate())
Es ist vielleicht nicht offensichtlich, dass die DATEADD negativ, um unter Verwendung von gewünschten jedoch viele Anzahl der Tage, um zurück zu gehen.
Wenn Sie alle Zeilen in diesem Zeitpunkt wollte:
SELECT t.*
FROM NEWS t
WHERE t.date BETWEEN DATEADD(day, -:url.d, getDate()) AND getDate())