Преобразование nvarchar в datetime и обратно в базу данных - PullRequest
0 голосов
/ 19 апреля 2019

Мне передали таблицу, в которую столбец Date был загружен как nvarchar (50).

Я более или менее понял, как преобразовать его в datetime.

select convert(datetime, Date_Time_In, 101)
FROM [DB].[dbo].[table]

Но у меня возникает проблема, когда он не пропускает часть времени столбца.Кроме того, как бы мне положить это обратно в таблицу, или просто конвертировать в таблицу с конкретным кодом SQL.Эта база данных имеет около 30 миллионов строк и более 160 столбцов.

Конечной целью является попытка сортировки моих данных, поскольку я пытаюсь использовать следующее:

SELECT * 
  FROM [DB].[dbo].[table]

  WHERE Date_Time_In between '1/1/2019 01:00:00 PM' and '4/1/2019 01:00:00 PM'

И он просто запрашивает все даты.


* Запросы при преобразовании в формат даты и времени 101

enter image description here После <----------------> До enter image description here

Ответы [ 3 ]

0 голосов
/ 19 апреля 2019

Если вы храните дату в виде строки, функции даты не будут работать. Полная остановка. У вас есть текст, а не даты.

Чтобы создать иллюзию, что у вас есть даты, чтобы вы могли использовать функции даты, вам нужно сделать что-то ужасное, подобное этому (которое будет работать вечно, потому что предикат WHERE не является SARGable из-за вызова функции ):

SELECT 
  * 
FROM 
  [DB].[dbo].[table]

WHERE 
  CONVERT(DATETIME, Date_Time_In, 101) 
    BETWEEN '1/1/2019 01:00:00 PM' AND '4/1/2019 01:00:00 PM';

Лучшими решениями будут:

1) Исправьте тип данных в текущем столбце (я знаю; устаревшая система, довольно много записей и т. Д., Делая это маловероятным, но если вы можете это сделать, WOO HOO!)

или

2) Добавить номер столбца 161 как сохраненный вычисляемый столбец, который на самом деле является DATETIME

ALTER TABLE [DB].[dbo].[table]
ADD DateTimeIn AS TRY_PARSE(Date_Time_In AS DATETIME) PERSISTED;
0 голосов
/ 19 апреля 2019

Короткий ответ: вам нужно привести обе стороны сравнения к одному и тому же типу даты.

Длинный ответ: вам нужно исправить основную структуру этой таблицы.Типы данных очень важны, и хранение всего в виде «строки» просто вызовет проблемы в будущем, когда кто-то захочет сообщить об этих данных.Я надеюсь, что следующий пример поможет проиллюстрировать это.Сначала посмотрите, что происходит с меткой времени, когда она приводится или преобразуется в различные типы.Затем посмотрите, что происходит, когда эти типы используются в сравнении.Лучше хранить метку времени не как NVARCHAR (50), а как DATETIME, DATETIME2 или DATE, в зависимости от того, насколько точной должна быть ваша точность.

SELECT CAST('1/1/2019 01:00:00 PM' AS DATETIME) betweenStart, 
       CAST('4/1/2019 01:00:00 PM' AS DATETIME) betweenEnd
SELECT CONVERT(DATETIME, '1/1/2019 01:00:00 PM', 101) betweenStart, 
       CONVERT(DATETIME, '4/1/2019 01:00:00 PM', 101) betweenEnd
-- betweenStart              betweenEnd
-- 2019-01-01 13:00:00.000  2019-04-01 13:00:00.000

SELECT CAST('1/1/2019 01:00:00 PM' AS DATETIME2) betweenStart, 
       CAST('4/1/2019 01:00:00 PM' AS DATETIME2) betweenEnd
SELECT CONVERT(DATETIME2, '1/1/2019 01:00:00 PM', 101) betweenStart, 
       CONVERT(DATETIME2, '4/1/2019 01:00:00 PM', 101) betweenEnd
-- betweenStart              betweenEnd
-- 2019-01-01 13:00:00.0000000  2019-04-01 13:00:00.0000000

SELECT CAST('1/1/2019 01:00:00 PM' AS DATE) betweenStart, 
       CAST('4/1/2019 01:00:00 PM' AS DATE) betweenEnd
SELECT CONVERT(DATE, '1/1/2019 01:00:00 PM', 101) betweenStart, 
       CONVERT(DATE, '4/1/2019 01:00:00 PM', 101) betweenEnd
-- betweenStart              betweenEnd
-- 2019-01-01                2019-04-01

IF OBJECT_ID('tempdb..#t') IS NOT NULL
    BEGIN
        DROP TABLE #t
    END
CREATE TABLE #t(
    myIdCol INT IDENTITY(1,1),
    Date_Time_In NVARCHAR(50)
)
INSERT INTO #t
VALUES('10/24/2018 12:52:10 PM'), 
('10/26/2018 3:53:45 PM'), 
('10/26/2018 3:53:45 PM'), 
('1/1/2019 3:53:45 PM'), 
('4/1/2019 12:59:00 PM'), 
('4/1/2019 01:00:01 PM')

SELECT * FROM #t WHERE Date_Time_In BETWEEN '1/1/2019 01:00:00 PM' AND '4/1/2019 
01:00:00 PM'
--  myIdCol   Date_Time_In
--  1   10/24/2018 12:52:10 PM
--  2   10/26/2018 3:53:45 PM
--  3   10/26/2018 3:53:45 PM
--  4   1/1/2019 3:53:45 PM
SELECT * 
FROM #t 
WHERE CAST(Date_Time_In AS DATETIME) BETWEEN 
      CAST('1/1/2019 01:00:00 PM' AS DATETIME) 
      AND 
      CAST('4/1/2019 01:00:00 PM' AS DATETIME)
--  myIdCol Date_Time_In
--  4   1/1/2019 3:53:45 PM
--  5   4/1/2019 12:59:00 PM
SELECT * 
FROM #t 
WHERE CAST(Date_Time_In AS DATETIME2) BETWEEN 
      CAST('1/1/2019 01:00:00 PM' AS DATETIME2) 
      AND 
      CAST('4/1/2019 01:00:00 PM' AS DATETIME2)
--  myIdCol Date_Time_In
--  4   1/1/2019 3:53:45 PM
--  5   4/1/2019 12:59:00 PM
SELECT * 
FROM #t 
WHERE CAST(Date_Time_In AS DATE) BETWEEN 
      CAST('1/1/2019 01:00:00 PM' AS DATE) 
      AND 
      CAST('4/1/2019 01:00:00 PM' AS DATE)
--  myIdCol Date_Time_In
--  4   1/1/2019 3:53:45 PM
--  5   4/1/2019 12:59:00 PM
--  6   4/1/2019 01:00:01 PM
0 голосов
/ 19 апреля 2019

Если вам не нужна часть времени, используйте

CONVERT(datetime, Date_Time_In, 111)

Чтобы заменить исходный столбец, создайте новый столбец, заполните его преобразованными датами, переименуйте исходный столбец, присвойте оригинальное имяновый столбец.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...