Witam,
czy jest możliwość stworzenia dodatkowych wierszy na podstawie zakresu dat.
W tabeli mssql mam wiersz i zakres dat np. 2021-08-10 do 2021-08-13 i na podstawie tego w oracle chciałbym stworzyć 4 wiersze gdzie data to będzie 2021-08-10, 2021-08-11, 2021-08-12 i 2021-08-13. Czy przerabiał ktoś podobny problem? Chciałbym to wykonać na poziomie sql.
Pozdrawiam
To ja odpowiem klasykiem Jest słowo 'witam' na początku listu? To nie odpowiadam
A odpowiadając na twoje pytanie:
- Czy masz połączenie z mssql do Oracla? (Możesz robić zdalnie inserty z mssql do Oracla?)
- Czy to musi być SQL? W SQLu chyba się nie da czegoś takiego wyrzeźbić, ale w T-SQLu już pewnie tak (jest pętla, żeby przeiterować te 4 razy)
Ja Oracla to widziałem tylko w ofertach pracy ;)
Nie jest trudne stworzenie w TSQL Selecta, w którym będziesz miał zwielokrotnione rekordy, w których zakres dat zawiera więcej, niż jeden dzień, ale najpierw kilka pytań pomocniczych:
- Która to wersja MS SQLa?
- Jak długie potencjalnie są okresy, które należy "rozbić" na wiele rekordów?
- Jak wiele masz obiektów / kolumn we wszystkich tabelach w bazie? Tu pomocne będą zapytania:
SELECT COUNT(*) FROM SYS.COLUMNS
SELECT COUNT(*) FROM SYS.ALL_OBJECTS
- Czy "zakres dat" to dwie osobne kolumny przechowujące datę początkową i końcową, czy też może String z dwiema datami? Jeśli dwie kolumny, to czy wpisujesz również czas (godziny/minuty)?
- Czy może się zdarzyć, ze jeden z rekordów ma wyłącznie datę początkową, lub końcową? Co wówczas?
W oracle jest takie coś:
select date'2021-08-10' + level - 1 dt
from dual
connect by level <= (
date'2021-08-13' - date'2021-08-10' + 1
)
w MSSQL i też Oracle możesz też użyć recursive subqueties - ale w oracle coś to nie do końca bangla do wersji 12 dla dat: https://paulzipblog.wordpress.com/2017/06/01/recursive-subquery-factoring-date-bug-in-11gr2/
Dane będą przenoszone dts'em z mssql do oracle na data są dwie kolumny typu date, zakres data od - data do i na godzinę tez są 2 kolumny godzina od i godzina do. Dane będą z zakresu tygodniowego lub dwutygodniowego
Ja raczej postgresowiec gdzie mam generate_series ale może poniższe linki będą pomocne. Szczególnie to z dual jest ciekawe
https://www.oracletutorial.com/oracle-basics/oracle-interval/
https://stackoverflow.com/questions/58734097/trying-to-create-a-generate-series-function-in-oracle-db
Edit dopiero zauważyłem że rozwiązanie @immanuel_cunt jest lepsiejsze :)
Ja proponuję jednak funkcję okna
SELECT tabela.data_od
,tabela.data_do
,dateadd(day, numerki.numerek, tabela.data_od)
FROM tabela
INNER JOIN (
SELECT row_number() OVER (
ORDER BY (
SELECT NULL
)
) - 1 numerek
FROM sys.all_objects
) numerki ON numerki.numerek = datediff(day, tabela.data_od, tabela.data_do)
WHERE tabela.data_od <> tabela.data_do
Tylko ta funkcja okna zwraca date do i nic więcej.
Użyłem takiej funkcji lecz gubi się, gdy są dwa zakresy czyli dwa wiersze
SELECT DATEADD(DAY, nbr - 1, @StartDate)
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
FROM sys.columns c
) nbrs
WHERE nbr - 1 <= DATEDIFF(DAY, @StartDate, @EndDate)
fifa1k1 napisał(a):
Tylko ta funkcja okna zwraca date do i nic więcej.
No jasne, że nic więcej, bo machnąłem babola :)
Poprawka:
SELECT tabela.data_od
,tabela.data_do
,dateadd(day, numerki.numerek, tabela.data_od)
FROM tabela
INNER JOIN (
SELECT row_number() OVER (
ORDER BY (
SELECT NULL
)
) - 1 numerek
FROM sys.all_objects
) numerki ON numerki.numerek <= datediff(day, tabela.data_od, tabela.data_do)
.
fifa1k1 napisał(a):
Użyłem takiej funkcji lecz gubi się, gdy są dwa zakresy czyli dwa wiersze
SELECT DATEADD(DAY, nbr - 1, @StartDate)
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
FROM sys.columns c
) nbrs
WHERE nbr - 1 <= DATEDIFF(DAY, @StartDate, @EndDate)
Założenia były takie, że masz w tabeli wiersz, a w nim dwie daty. Do tych założeń napisałem Ci gotowca (z błędem, który poprawiłem) - wystarczy podmienić nazwę tabeli i kolumn z datami - nie podałeś ich.
http://sqlfiddle.com/#!18/7403b/4/1
Teraz założenia zmieniasz dodając obsługę jakichś zmiennych. Wytłumacz, czemu, to może coś poradzimy...
W sumie możesz to zrobić za pomocą cte, tabelki tymczasowej i paru innych sposobów.