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

Вземете записите от миналия месец в SQL сървър

Всички съществуващи (работещи) отговори имат един от двата проблема:

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

1. Игнорирани индекси:

В по-голямата си част, когато колона, която се търси, има извикана функция (включително имплицитно, като за CAST ), оптимизаторът трябва да игнорира индекси в колоната и да търси във всеки запис. Ето един бърз пример:

Имаме работа с времеви отпечатъци и повечето RDBMS са склонни да съхраняват тази информация като нарастваща стойност от някакъв вид, обикновено long или BIGINTEGER брой мили-/наносекунди. По този начин текущото време изглежда/се съхранява така:

1402401635000000  -- 2014-06-10 12:00:35.000000 GMT

Не виждате стойността „Година“ ('2014'). ) там, нали? Всъщност има доста сложна математика за превод напред и назад. Така че, ако извикате някоя от функциите на частта за извличане/дата в търсената колона, сървърът трябва да извърши цялата тази математика, само за да разбере дали можете да я включите в резултатите. При малки таблици това не е проблем, но тъй като процентът на избраните редове намалява, това става все по-голямо и по-голямо изтичане. Тогава в този случай го правите втори път, защото питате за MONTH ... добре, разбирате.

2. Непредвидени данни:

В зависимост от конкретната версия на SQL Server и типовете данни на колони, като се използва BETWEEN (или подобни включващи горни граници:<= ) може да доведе до избор на грешни данни. По същество е възможно да включите данни от полунощ на „следващия“ ден или да изключите част от записите за „текущия“ ден.

Това, което трябва да правиш:

Така че имаме нужда от начин, който е безопасен за нашите данни и ще използва индекси (ако е жизнеспособно). Тогава правилният начин е от вида:

WHERE date_created >= @startOfPreviousMonth AND date_created < @startOfCurrentMonth

Като се има предвид, че има само един месец, @startOfPreviousMonth може лесно да бъде заменен/изведен от:

DATEADD(month, -1, @startOCurrentfMonth)

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

DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)

Кратко обяснение тук. Първоначалният DATEDIFF(...) ще получи разликата между началото на текущата ера (0001-01-01 - AD, CE, каквото и да е), по същество връщайки голямо цяло число. Това е броят на месеците до началото на текущия месец. След това добавяме това число към началото на ерата, което е в началото на дадения месец.

Така че пълният ви скрипт може/трябва да изглежда подобно на следното:

DECLARE @startOfCurrentMonth DATETIME
SET @startOfCurrentMonth = DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0)

SELECT *
FROM Member
WHERE date_created >= DATEADD(month, -1, @startOfCurrentMonth) -- this was originally    misspelled
      AND date_created < @startOfCurrentMonth

Всички операции с дата се изпълняват само веднъж, върху една стойност; оптимизаторът е свободен да използва индекси и няма да бъдат включени неправилни данни.



  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 Server преобразува низ в дата и час

  2. Как да добавите първичен ключ към съществуваща таблица в SQL Server (T-SQL примери)

  3. @@DATEFIRST – Вземете първия ден от седмицата в SQL Server

  4. Как да генерирате тестови данни в SQL Server

  5. pyodbc - много бавна скорост на масово вмъкване