2016-01-05 3 views
0

Я создаю приложение, которое по сути является проверкой целостности между двумя базами данных - одна из них - MSSQL, а другая - старый поставщик Btrieve. В рамках требований все столбцы для каждой таблицы необходимо сравнить, чтобы обеспечить соответствие данных. В настоящее время мы просматриваем каждую таблицу, получаем базовый счет таблицы в обеих БД, а затем углубляемся в столбцы. Для числовых полей мы делаем простой SUM, а для текстовых полей суммируем длину столбца для каждой строки. Если они совпадают в обеих БД, это хороший индикатор, который данные перенесли правильно.«Суммирование» поля даты в SQL - любые идеи?

Все это прекрасно работает, но мне нужно разработать нечто похожее для полей datetime. Очевидно, мы не можем SUM эти поля, поэтому мне интересно, есть ли у кого-нибудь идеи по наилучшему подходу к этому. Я думал, может быть, секунды с определенной даты, но число будет огромным.

Любые другие идеи? Благодаря!

+0

хэш строки .... –

ответ

0

Самый простой ответ для меня заключался бы в преобразовании полей даты или даты и времени в целые числа с одинаковым форматом. YYYYMMDD или YYYYMMDDHHmmss работают очень хорошо, пока ваши форматы используют ведущие нули.В SQL Server, вы можете сделать что-то вроде:

SELECT SUM(CAST(REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(20),DateTimeColumn,120),' ',''),':',''),'-','') AS BIGINT)) ..... 

С другой стороны, вы можете конвертировать их либо количество дней от заданной даты ('1970-01-01'), или количество секунд от заданной даты ('1970-01-01 00:00:00'), если вы используете время.

SELECT SUM(DATEDIFF(DAY,'19700101',DateColumn)) .... 

Я не достаточно знаком с Btrieve, чтобы узнать, какие функции доступны для дат форматирования.

+0

Большое спасибо - я пошел с этим решением в и, и это сработало! – Chris

-1

Я думаю, что вы можете сделать что-то подобное на стороне SQL Server, чтобы найти значение центра («среднее») столбца. Затем используйте это значение на стороне Btrieve, чтобы избежать проблем с переполнением, где я предполагаю, что вы более ограничены.

-- January 1, 2000 value pulled out of the air as a stab in the dark 
select 
    dataadd(
     second, 
     avg(cast(datediff(datediff(second, '20000101', <data>) as bigint)), 
     '20000101' 
    ) /* find the center */ 

Я не удивлюсь, если вам пришлось прибегнуть к типу с плавающей точкой с Btrieve или разделить отсканированные на меньшие диапазоны, чтобы избежать промежуточных сумм, которые получают слишком большой. И вы можете использовать курсор и рандомизировать упорядочение строк, чтобы вы не ударили их в отсортированном порядке, который вызывает переполнение. На данный момент я просто размышляю, так как я не видел ни одной из данных, и мои знания о Btrieve настолько древние и минимальные для начала.

У меня также есть ощущение, что некоторые из этих усилий связаны с удовлетворением некоторого беспокойства со стороны нетехнических заинтересованных сторон. Я уверен, что вы могли бы придумать контрольные суммы и хэши, которые будут работать лучше, но эта концепция суммирования - та, которую они могут понять, и успокоит их, вместо того, чтобы быть несколько проще реализовать быстро.

0

Используя «За исключением» в SQL на строках числовых полей, вы можете сравнить количество дат в обеих таблицах. Для старого источника вы можете сгенерировать оператор select с помощью excel или в собственной базе данных и донести до SQL Server. Для демонстрационной цели я использовал две таблицы и показываю, кроме примера ниже.

IF EXISTS (SELECT * FROM sys.objects 
      WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[DateCompareOld]') AND 
      TYPE IN (N'U')) 
DROP TABLE [dbo].[DateCompareOld] 
GO 

CREATE TABLE dbo.DateCompareOld 
(
AsOf DATETIME 
) 

INSERT INTO DateCompareOld 
SELECT '01/01/2016' UNION ALL 
SELECT '01/01/2016' UNION ALL 
SELECT '01/01/2016' UNION ALL 
SELECT '01/02/2016' UNION ALL 
SELECT '01/02/2016' UNION ALL 
SELECT '01/02/2016' 


IF EXISTS (SELECT * FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[DateCompareNew]') AND TYPE IN (N'U')) 
DROP TABLE [dbo].[DateCompareNew] 
GO 

CREATE TABLE dbo.DateCompareNew 
(
AsOf DATETIME 
) 

INSERT INTO DateCompareNew 
SELECT '01/01/2016' UNION ALL 
SELECT '01/01/2016' UNION ALL 
SELECT '01/01/2016' UNION ALL 
SELECT '01/02/2016' UNION ALL 
SELECT '01/02/2016' UNION ALL 
SELECT '01/02/2016' 

SELECT AsOf,COUNT(*) AsOfCount 
FROM DateCompareOld 
GROUP BY AsOf 
Except 
SELECT AsOf,COUNT(*) AsOfCount 
FROM DateCompareNew 
GROUP BY AsOf 
+2

Пожалуйста, объясните, что это неправильно downvote это?. Помогает мне улучшить его в следующий раз. Благодарю. – CodeEnhancer

+0

Я не спускал вниз. Этот вопрос не дает большого понимания процесса миграции/проверки целостности. Я подозреваю, что вся цель состоит в том, чтобы убедиться, что данные, которые отправляются на SQL Server, выполнены правильно. Но это лишь просвещенная догадка с моей стороны. – shawnt00

0

Если диапазон дат используются строки в базе данных не является экстремальным (например, даты астрономических звезд рождаясь и умирая), она должна быть столь же действительным для преобразования даты в целое число. Это можно сделать любым из нескольких способов и немного зависит от конкретной базы данных, но преобразование 2016-01-04 в 20,160,104 будет работать нормально.

Даже SQL Server допускает ORD(date_field) подобные выражения для получения внутреннего представления. Но это также может быть сделано в портативном, системе агностика средства как

datediff(day, 'January 1, 1901', date_field) 

если отслеживание дней является достаточным, или

datediff(second, 'January 1, 1901', date_field) 

если отслеживание секунд требуются.

0

Может быть, это не очень поможет, возможно, что-то:

declare @d1 datetime; set @d1 = '2016-01-05 12:09' 
declare @d2 datetime; set @d2 = '1970-04-05 07:09' 
declare @d3 datetime; set @d3 = '1999-12-12 23:05' 
declare @d4 datetime; set @d4 = '1999-12-12 23:06' 

declare @i1 bigint 
declare @i2 bigint 
declare @i3 bigint 
declare @i4 bigint 

select @i1 = convert(bigint, convert(timestamp, @d1)) 
select @i2 = convert(bigint, convert(timestamp, @d2)) 
select @i3 = convert(bigint, convert(timestamp, @d3)) 
select @i4 = convert(bigint, convert(timestamp, @d4)) 

select @i1 
select @i2 
select @i3 
select @i4 

select @i1^@i2^@i3^@i4 
+0

Я думаю, что внутренние представления дат могут различаться между двумя системами. – shawnt00

+0

@ shawnt00 Yeap ... Я полностью забыл, что мы говорим о двух разных системах. Но, возможно, он мог применить логику в приложении, которое он разрабатывает. Один вопрос. Что вы подразумеваете под «внутренними представлениями»? – shadow

+0

Вы используете побитовые операции там, и я в основном имел в виду битовые шаблоны/значения, которые кодируют значения даты. – shawnt00

Смежные вопросы