Piotr Warda

Piotr Warda
informatyk-ekonomist
a

Temat: MS SQL

Witam,

Szukam rozwiązania, które pozwoli mi zaktualizować część rekordów w jednej tabeli na podstawie zapisów w innej tabeli.

Tabela A ma kilka pól: id, kod, nazwa, wartosc
1, 20, aa, 100.00
2, 21, bb, 45.0
3, 21, bb, 60.0
4, 22, aa, 100.00

Tabela B ma identyczne pola, ale numeracja w polu id różni się od numeracji w polu id z tabeli A.

6, 20, aa, 100.0
7, 21, bb, 78.0
8, 21, bb, 45.0
9, 22, aa, 100.00

W każdej tabeli unikalne są wartości pól id. W polu kod wartości mogą się powtarzać, podobnie jak w polu nazwa.

Potrzebuję zrobić tak:

z tabeli A dla określonego zakresu pola kod pobrać dane w z pól nazwa i wartość i dla tego samego pola kod, w tej samej kolejności pól nazwa zaktualizować wartość.

czyli np.:
z rekordu: 2, 21, bb, 45.0
przenieść wartość pola wartosc do rekordu 7, 21, bb, 78.0
itd.

Zwykłe update nie załatwi sprawy, gdyż nie ma stałego przesunięcia numeracji rekordów między jedną tabelą a drugą tabelą. Próbowałem to zrobić korzystając z kursorów, ale nie można zadeklarować kursora ze zmienną we frazie where.

Dodatkowo nie wchodzi w rachubę korzystanie zmiana nazwy tabeli B czy jej czyszczenie - może tylko nastąpić aktualizacja wartości.

Pozdrawiam.

Piotrek
Marcin Miga

Marcin Miga Programista. Po
prostu programista.

Temat: MS SQL

Dodaj sobie do każdej z tych tabel (lub na widoku) kolumnę z lp dla danej pary (kod, nazwa). Będziesz wtedy miał:
TABELA A:
1, 20, aa, 100.00, 1
2, 21, bb, 45.0, 1
3, 21, bb, 60.0, 2
4, 22, aa, 100.00, 1
TABELA B
6, 20, aa, 100.0, 1
7, 21, bb, 78.0, 1
8, 21, bb, 45.0, 2
9, 22, aa, 100.00, 1

I połącz te tabele po trzech polach: (kod, nazwa, lp)

pozdrawiaMM
Piotr Sebastian Curyło

Piotr Sebastian Curyło właściciel, Lan Set

Temat: MS SQL

czy dobrze rozumiem?
Jeśli tabela_A.kod==tabela_B.kod i tabela_A.nazwa==tabela_b.nazwa
to zrób wpis tabela_B.wartosc=tabela_A.wartosc
dla jednego rekordu
to w takim razie zwykły update jak tak ładnie nazywasz poradzi sobie z tym
A jeśli chcesz dopisać nowe to wtedy INSERT
Grzegorz K.

Grzegorz K. Data & Analytics
Engineer

Temat: MS SQL

Czy para [kod], [nazwa] jest unikalna w każdej z tych tabel?

Jeśli nie , to czy dana para np. (20 , 'aa') jest reprezentowana w obu tabelach przez tą samą liczbę rekordów ?

A jeśli liczba rekordów w obu tabelach dla wybranej pary może być różna, to na czym ma polegać update - czy np. część wartości ma być nadpisana, a część nie ?

opis nie przedstawia problemu jednoznacznie.

pozdrawiamGrzegorz K. edytował(a) ten post dnia 25.01.13 o godzinie 18:03
Lukasz Bizon

Lukasz Bizon Senior SQL Server
Administrator,
GlaxoSmithKline

Temat: MS SQL

Z tego co widze mozesz zrobic zwykly update poniewaz masz te same kody w obu tablicach. Nie musisz koniecznie laczyc tablic na podstawie pola id.

update tblB set wartosc=tblA.Wartosc
FROM tblB INNER JOIN tblA on tblA.kod=tblB.kod and tblA.Nazwa=tblB.Nazwa
Piotr Warda

Piotr Warda
informatyk-ekonomist
a

Temat: MS SQL

Witam,

Tak - para liczba rekordów kod+nazwa w każdej z tabel jest taka sama, gdyż inaczej nie byłaby możliwa aktualizacja tylko konieczne było dodawanie rekordów.

Póki co zrobiłem rozwiązanie z podwójną pętlą while (nie zależy mi na czasie), wybieraniem rekordów, zliczaniem rekordów dla tej samej wartości pola nazwa oraz aktualizowaniem pojedynczych zapisów.

Pozdrawiam,
Grzegorz K.

Grzegorz K. Data & Analytics
Engineer

Temat: MS SQL

Piotr Warda:
Póki co zrobiłem rozwiązanie z podwójną pętlą while (nie zależy mi na czasie), wybieraniem rekordów, zliczaniem rekordów dla tej samej wartości pola nazwa oraz aktualizowaniem pojedynczych zapisów.

Optymalizator zapytań zapewne nie bardzo się ucieszył z podwójnego while'a - gdyby mógł mówić, zapewne byłoby to coś bardzo brzydkiego - "motyla noga" czy jakoś tak :)

Myślę, że mógłbyś skorzystać z propozycji Marcina. Poniżej jakiś przykładowy kod ( oczywiście do dopracowania/przerobienia - indeksy itp.)



-- TAB 1
---------------------------------------
if object_id('tempdb..#Tab1') is not null
drop table #Tab1

Create table #Tab1(
id int not null identity primary key,
kod int,
Nazwa varchar(10),
Kwota money
)

insert into #Tab1(kod, Nazwa,Kwota)
select 100, 'A', 10
union select 100, 'B', 20
union select 100, 'B', 30
union select 200, 'A', 10
union select 200, 'A', 20
union select 200, 'A', 30
union select 200, 'B', 50

-- TAB 2
---------------------------------------
if object_id('tempdb..#Tab2') is not null
drop table #Tab2

Create table #Tab2(
id int not null identity(100,1) primary key,
kod int,
Nazwa varchar(10),
Kwota money
)

insert into #Tab2(kod, Nazwa,Kwota)
select 100, 'A', 20
union select 100, 'B', 40
union select 100, 'B', 60
union select 200, 'A', 20
union select 200, 'A', 40
union select 200, 'A', 60
union select 200, 'B', 100


-- UPDATE
;with CTE_1 as (
select
*,
row_number() over (partition by kod,nazwa order by id) as LP
from #Tab1
),
CTE_2 as (
select
*,
row_number() over (partition by kod,nazwa order by id) as LP
from #Tab2
)
update modyfikowana
set Kwota = c2.Kwota
from #Tab1 as modyfikowana
join CTE_1 as c1
on (c1.id = modyfikowana.id
and c1.kod = modyfikowana.kod)
join CTE_2 as c2
on (c1.kod = c2.kod
and c1.nazwa = c2.nazwa
and c1.lp = c2.lp)

Grzegorz K. edytował(a) ten post dnia 28.01.13 o godzinie 18:21



Wyślij zaproszenie do