Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Serwer SQL POMIĘDZY

Wymyślenie sposobu na użycie BETWEEN z tabelą taką, jaka jest, będzie działać, ale w każdym przypadku będzie gorsza:

  • W najlepszym wypadku zużyje więcej procesora, aby wykonać jakieś obliczenia na wierszach, zamiast pracować z nimi jako datami.
  • W najgorszym przypadku wymusi to skanowanie każdego wiersza w tabeli, ale jeśli Twoje kolumny mają indeksy, to przy odpowiednim zapytaniu możliwe jest wyszukiwanie. Może to być OGROMNA różnica w wydajności, ponieważ wymuszenie ograniczeń w klauzuli BETWEEN spowoduje wyłączenie korzystania z indeksu.

Zamiast tego proponuję następujące rozwiązanie, jeśli masz indeks w swoich kolumnach dat i w ogóle zależy Ci na wydajności:

DECLARE
   @FromDate date = '20111101',
   @ToDate date = '20120201';

SELECT *
FROM dbo.YourTable T
WHERE
   (
      T.[Year] > Year(@FromDate)
      OR (    
         T.[Year] = Year(@FromDate)
         AND T.[Month] >= Month(@FromDate)
      )
   ) AND (
      T.[Year] < Year(@ToDate)
      OR (
         T.[Year] = Year(@ToDate)
         AND T.[Month] <= Month(@ToDate)
      )
   );

Jednak zrozumiałe jest, że nie chcesz używać takiej konstrukcji, ponieważ jest to bardzo niewygodne. Więc tutaj jest zapytanie kompromisowe, które przynajmniej używa obliczeń numerycznych i będzie zużywało mniej procesora niż obliczenia konwersji daty na ciąg (choć nie wystarczająco mniej, aby zrekompensować wymuszone skanowanie, które jest prawdziwym problemem z wydajnością).

SELECT *
FROM dbo.YourTable T
WHERE
   T.[Year] * 100 + T.[Month] BETWEEN 201111 AND 201202;

Jeśli masz indeks na Year , możesz uzyskać duży wzrost, przesyłając zapytanie w następujący sposób, które ma możliwość wyszukiwania:

SELECT *
FROM dbo.YourTable T
WHERE
   T.[Year] * 100 + T.[Month] BETWEEN 201111 AND 201202
   AND T.[Year] BETWEEN 2011 AND 2012; -- allows use of an index on [Year]

Chociaż to łamie Twój wymóg używania jednego BETWEEN wyrażenie, nie jest zbyt bolesne i będzie działać bardzo dobrze z Year indeks.

Możesz także zmienić swój stół. Szczerze mówiąc, używanie oddzielnych liczb dla części dat zamiast pojedynczej kolumny z typem danych daty nie jest dobre. Powodem, dla którego nie jest to dobre, jest dokładny problem, z którym się teraz borykasz - bardzo trudno jest zapytać.

W niektórych scenariuszach hurtowni danych, w których zapisywanie bajtów ma duże znaczenie, mógłbym wyobrazić sobie sytuacje, w których można przechowywać datę jako liczbę (np. 201111 ), ale nie jest to zalecane. najlepsze rozwiązaniem jest zmiana tabeli tak, aby używała dat zamiast dzielenia wartości liczbowej miesiąca i roku. Po prostu zapisz pierwszy dzień miesiąca, uznając, że jest to cały miesiąc.

Jeśli zmiana sposobu korzystania z tych kolumn nie jest możliwa, ale nadal możesz zmienić swoją tabelę, możesz dodać utrwaloną kolumnę obliczaną:

ALTER Table dbo.YourTable
   ADD ActualDate AS (DateAdd(year, [Year] - 1900, DateAdd(month, [Month], '18991201')))
   PERSISTED;

Dzięki temu możesz po prostu zrobić:

SELECT *
FROM dbo.YourTable
WHERE
   ActualDate BETWEEN '20111101' AND '20120201';

PERSISTED słowo kluczowe oznacza, że ​​chociaż nadal będziesz otrzymywać skanowanie, nie będziesz musiał wykonywać żadnych obliczeń w każdym wierszu, ponieważ wyrażenie jest obliczane przy każdym INSERT lub UPDATE i przechowywane w wierszu. Ale możesz uzyskaj wyszukiwanie, jeśli dodasz indeks do tej kolumny, co sprawi, że będzie działała bardzo dobrze (chociaż w sumie nie jest to tak idealne, jak zmiana na użycie rzeczywistej kolumny daty, ponieważ zajmie więcej miejsca i wpłynie na INSERT i AKTUALIZACJE):

CREATE NONCLUSTERED INDEX IX_YourTable_ActualDate ON dbo.YourTable (ActualDate);

Podsumowanie:jeśli naprawdę nie możesz w żaden sposób zmienić tabeli, będziesz musiał w jakiś sposób pójść na kompromis. Nie będzie możliwe uzyskanie prostej składni, która będzie również działać dobrze, gdy daty są przechowywane w osobnych kolumnach.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL CLR zwraca dwie nowe kolumny

  2. Wstaw zbiorczo ścieżkę pliku jako parametr procedury składowanej

  3. Jak sprawdzić, czy kolumna tekstowa programu SQL Server jest pusta?

  4. podziel alfa i numeryczne za pomocą sql

  5. Jak zwrócić wiele wartości w jednej kolumnie (T-SQL)?