Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

SQL Server МЕЖДУ

Измислянето на начин за използване на BETWEEN с таблицата, каквато е, ще работи, но във всеки случай ще има по-лоша производителност:

  • В най-добрия случай ще изразходва повече CPU, за да направи някакъв вид изчисление на редовете, вместо да работи с тях като дати.
  • В най-лошия случай ще принуди сканиране на таблица на всеки ред в таблицата, но ако вашите колони имат индекси, тогава с правилната заявка е възможно търсене. Това може да е ОГРОМНА разлика в производителността, защото налагането на ограниченията в клауза BETWEEN ще деактивира използването на индекса.

Предлагам следното вместо това, ако имате индекс на вашите колони с дати и изобщо не ви пука за ефективността:

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

Разбираемо е обаче, че не искате да използвате такава конструкция, тъй като е много неудобна. Така че тук е компромисна заявка, която поне използва числово изчисление и ще използва по-малко CPU от изчислението за преобразуване на дата в низ (макар и не достатъчно, за да компенсира принудителното сканиране, което е истинският проблем с производителността).

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

Ако имате индекс на Year , можете да получите голям тласък, като изпратите заявката по следния начин, която има възможност да търси:

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]

Въпреки че това нарушава изискването ви за използване на един BETWEEN израз, не е много по-болезнено и ще се представи много добре с Year индекс.

Можете също да промените масата си. Честно казано, използването на отделни числа за вашите части от датата вместо една колона с тип данни за дата не е добро. Причината, поради която не е добре, е точният проблем, пред който сте изправени в момента – много е трудно да се направи запитване.

В някои сценарии за съхранение на данни, където запазването на байтове има голямо значение, мога да си представя ситуации, при които можете да съхранявате датата като число (като 201111 ), но това не се препоръчва. Най-добрият решението е да промените таблицата си, за да използвате дати, вместо да разделяте числовата стойност на месеца и годината. Просто запазете първия ден от месеца, като разпознавате, че той остава за целия месец.

Ако промяната на начина, по който използвате тези колони, не е опция, но все пак можете да промените таблицата си, тогава можете да добавите постоянна изчислена колона:

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

С това можете просто да направите:

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

PERSISTED ключова дума означава, че въпреки че все още ще получите сканиране, то няма да трябва да прави изчисления на всеки ред, тъй като изразът се изчислява на всяко INSERT или UPDATE и се съхранява в реда. Но вие можете получите търсене, ако добавите индекс към тази колона, което ще я направи много добра (въпреки че като цяло това все още не е толкова идеално, колкото промяната да използвате действителна колона с дата, защото ще отнеме повече място и ще засегне INSERT и АКТУАЛИЗАЦИИ):

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

Резюме:ако наистина не можете да промените таблицата по никакъв начин, тогава ще трябва да направите компромис по някакъв начин. Няма да е възможно да получите простия синтаксис, който искате, който също ще работи добре, когато вашите дати се съхраняват разделени в отделни колони.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Запитване за xml в sql сървър 2008

  2. След 13-ти ред Динамични и в 12-ти ред статични стойности с формула

  3. Как да използвам резултат от SQL оператор за избор във функцията dbo.fnSplit като вход

  4. Динамични централни колони в SQL Server

  5. Намиране на следващия ред в SQL заявката и изтриването му само ако предходният ред съвпада