Błąd systemu Azure ADF Błąd przepełnienia arytmetycznego po przekształceniu wyrażenia do danych typu int

0

Pytanie

Pracuję z azure ADF, i mam problem podczas wykonywania tego zapytania w azure ADF:

SELECT COUNT(*) AS c
FROM TABLE 
WHERE CONVERT(date, (FORMAT(DATEADD(second, CONVERT(bigint, TS) / 1000, '19700101'), 'yyyy-MM-dd'))) = CONVERT(Date, GETDATE())

Wniosek-to błąd

Przepełnienie arytmetyczne

ale jeśli zmienię = Do >=zapytanie działa i zwraca wynik.

To TS to UNIXTIMESTAMP Podoba 1637680012264.

Za pomocą kombinacji >= i < to nie jest normalne, bo mam do czynienia z ciągłymi dni (muszę użyć WHERE TS IN (date1, date2, etc...)

Czy ktoś może mi pomóc? Z góry dziękuję

azure azure-data-factory sql sql-server
2021-11-23 15:02:27
2

Najlepsza odpowiedź

0

Najlepiej, ja bym zmienił tabelę do przechowywania datetime2 wartości, zamiast skomplikowanych śmieci epoki.

Ale, zakładając, że nie możesz naprawić projekt...

Zdaniem Ларну, nie chcesz stosować obliczenia do kolumny, i na pewno nie chcesz stosować FORMAT() z obu stron, boFORMAT() to absolutna pies.

Zamiast tego bym znalazł granicy na dziś i wykorzystał odkryty zakres. To sugeruje, że TS kolumna musi być bigint:

DECLARE @d date = GETDATE();

DECLARE @start bigint = DATEDIFF(SECOND, '19700101', @d),
        @end   bigint = DATEDIFF(SECOND, '19700101', DATEADD(DAY, 1, @d));

SELECT COUNT(*) AS c
FROM dbo.[TABLE]
WHERE TS >= @start * 1000 
  AND TS <  @end   * 1000;

Pozwala to uniknąć kosztów ogólnych na formatowanie, skomplikowanych i niepotrzebnych zwrotów konwersji (TS musi być, już jest bigintprawda , więc dlaczego bezpośrednia CONVERT()?).


Jeśli potrzebujesz nieprzylegające chcesz, dobrze, wciąż możemy zrobić to z o wiele mniejszym nadużyciem tabeli. Wystarczy utworzyć tabelę #temp lub zmiennej tabeli z obliczeniowe kolumnami, włóż tam kilka swoich dat, a następnie na zewnątrz dołącz do niej.

DECLARE @d table
(
  d datetime2, 
  s AS CONVERT(bigint, 
    DATEDIFF(SECOND, '19700101', d)) * 1000,
  e AS CONVERT(bigint, 
    DATEDIFF(SECOND, '19700101', DATEADD(DAY, 1, d))) * 1000
);

INSERT @d(d) VALUES('20211123'),('20211007');

-- if you want a row per day:
SELECT d.d, COUNT(t.TS) AS c
FROM @d AS d
LEFT OUTER JOIN dbo.[TABLE] AS t
   ON  t.TS >= d.s
   AND t.TS <  d.e
GROUP BY d.d
ORDER BY d.d;

-- if you just want a total count:
SELECT COUNT(t.TS) AS c
FROM @d AS d
LEFT OUTER JOIN dbo.[TABLE] AS t
   ON  t.TS >= d.s
   AND t.TS <  d.e;

Znacznie więcej na temat nowoczesnych szkodliwych nawyków i najlepszych praktykach:

2021-11-23 15:46:34

Dziękuję, Aaron, mimo, że rozwiązanie to nie jest to, co szukałem, to mówisz moje polecenie: "To nie jest źródło błędu. DATEADD nigdy nie będzie w stanie dodać 3 mld sekund do 1970 roku. Tak, może być, podziel jeszcze raz i spróbuj dodać za minutę, jeśli interesuje cię tylko data, dokładność drugiego poziomu nie powinna być ważna. Czy możesz podać kilka przykładowych wartości dla TS i oczekiwane rezultaty dla nich". Dlatego przekształcił ZNACZNIK CZASU w DNIACH, dzieląc ją na 60*60*1000*24
Salvatore Bonanno

@SalvatoreBonанно, ale to wciąż bardzo nieskuteczny sposób na rozwiązanie problemu. Chcesz, aby matematyka była po drugiej stronie punktu "gdzie", uwierz mi. Jeśli tylko nie TS kolumna nie jest indeksowana, i wiesz dokładnie, że nigdy nie będziesz go indeksować.
Aaron Bertrand

Tak, widziałem rozwiązanie z pomocą tabeli tymczasowej. Najbardziej problematyczne jest to, że mogę mieć dostęp tylko do odczytu do tabeli ( tabela znajduje się w chmurze), więc nie wiem nic o indeksie na niej (to też może być widok!) . Tak więc, matematyczna zadanie rozwiązała problem w tej chwili, ale postaram się zoptymalizować jej, jak pan powiedział.
Salvatore Bonanno
-1

Powtórzyłem to w swoim lokalnym środowisku ADF i mógł z powodzeniem uzyskać wyniki.

Poniżej znajduje się przykładowa tabela:

Tutaj mam 3 linie z datą "2021-11-23" i 2 linie z '2021-11-24'. TS kolumna ma datę w formacie znacznik czasu UNIKSA i dt_format kolumna przeznaczona jest do wyświetlania TS kolumna w formacie daty.

enter image description here

TD:

Wykorzystując działanie wyszukiwania, otrzymasz liczbę wierszy, w których w kolumnie TS podana jest dzisiejsza data. (Używam twój kod z innej tabeli).

SELECT COUNT(*) AS c
FROM tb1 
WHERE CONVERT(date, (FORMAT(DATEADD(second, CONVERT(bigint, TS) / 1000, '19700101'), 'yyyy-MM-dd'))) = CONVERT(Date, GETDATE())

enter image description here

Wyjście:

enter image description here

2021-11-23 15:28:21

W innych językach

Ta strona jest w innych językach

Русский
..................................................................................................................
Italiano
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................