Problem z napisaniem procedury usuwającej ponadwymiarowe rekordy w T-SQL

0

Cześć. Ostatnio zacząłem trochę bawić się z T-SQL i wymyśliłem sobie taki kazus, który polega na tym, że mam w bazie danych w jednej z tabel zwielokrotnione rekordy, a powinien być tylko jeden wynik z (select z tej tabeli-screen 1 - zaznaczone są wszystkie rekordy zwielokrotnione oraz jeden właściwiy z id produktu 78)

screenshot-20220825220717.png
screen 1

I teraz mam tą procedurkę, która w moim zamyśle ma działać w ten sposób:

  1. Sprawdzam, czy w ogóle w tej tabeli są takie przypadki:
  2. Jeśli nie, to jest wyświetlony stosowny komunikat.
    Te 2 punkty mają być realizowane tą częścią kodu:
if 		(select COUNT (ProductID) as Ilosc from Products group by ProductName, SupplierID ) = 1
		begin
			print 'Nie ma ponadwymiarowych rekordów. Wszystko jest w porządku; pracuj dalej:)'
		end
  1. Jeśli tak, to kolejnym zapytaniem pokazuję w komunikacie ile jest ponadwymiarowym (bez tego, który powinien być).
  2. Następnie w kolejnym zapytaniu tworzę numery ID-ów do usunięcia .
  3. Tak przygotowaną listę jako podzapytanie przekazuję do delete'a, który ma usunąć te rekordy.
    Te 3 punkty mają być realizowane tak:
else
		begin
			set @IloscPonadwymiarowych = ((select COUNT (ProductID) as Ilosc from Products group by ProductName, SupplierID having count (ProductID) > 1) - 1)
			print concat ('Niestety w bazie są ponadwymiarowe rekordy do usunięcia, w liczbie ' ,cast (@IloscPonadwymiarowych as varchar),'.' ,' Teraz je usunę.') 
			set @IdDoUsunięcia = (select c.idprod from (select ProductID  as idprod, A.ProductName, ilosc, minimum as mmm from Products as B join (select ProductName, count (*) as ilosc, min (productID) as minimum from Products group by ProductName) as A on A.ProductName = B.ProductName) as c where c.idprod <> mmm)
			delete from Products where ProductID = @IdDoUsunięcia
		end

Tak wygląda cała procedura:

use Northwind
go
create or alter procedure UsunPonadwymiaroweRekordy
as begin
	declare @IdDoUsunięcia int, @IloscPonadwymiarowych int
if 		(select COUNT (ProductID) as Ilosc from Products group by ProductName, SupplierID ) = 1
		begin
			print 'Nie ma ponadwymiarowych rekordów. Wszystko jest w porządku; pracuj dalej:)'
		end
else
		begin
			set @IloscPonadwymiarowych = ((select COUNT (ProductID) as Ilosc from Products group by ProductName, SupplierID having count (ProductID) > 1) - 1)
			print concat ('Niestety w bazie są ponadwymiarowe rekordy do usunięcia, w liczbie ' ,cast (@IloscPonadwymiarowych as varchar),'.' ,' Teraz je usunę.') 
			set @IdDoUsunięcia = (select c.idprod from (select ProductID  as idprod, A.ProductName, ilosc, minimum as mmm from Products as B join (select ProductName, count (*) as ilosc, min (productID) as minimum from Products group by ProductName) as A on A.ProductName = B.ProductName) as c where c.idprod <> mmm)
			delete from Products where ProductID = @IdDoUsunięcia
		end
end

Jak uruchomię create procedure, to procedura dodaje się poprawnie do bazy, ale jak już robię jej wykonanie, to jest błąd:

screenshot-20220825223720.png

Po pierwsze nie działa if w pierwszej części kodu, bo i tak zawsze jest pokazany komunikat, że są rekordy do usunięcia, nawet jak nie ma zwielokrotnionych.
Po drugie tworząć listę id-ów do usunięcia serwer wymaga ode mnie wyniku skalarnego, a dostaje wektor. Próbowałem też zrobić wariant ze zmienną tabelaryczną, ale też nie to nie działało.
Mógłby któryś z kolegów-programistów spojrzeć na to łaskawym okiem i się wypowiedzieć, co robię nie tak;)
Z góry dzięki za wszelkie komentarze

2

Na telefonie nie napiszę zapytania, normalnie nie robi się takich printow, ale jak rozumiem to w celach edukacyjnych.

W całym tym kodzie zapominasz że możesz mieć kilka produktów zduplikowanych zmień warunek na:

If not exists(select COUNT (ProductID) from Products group by ProductName, SupplierID having count(productid)>1)

Nie możesz przypisać do jednego inta kilku wartości możesz usunąć te pliki posiłkując się joinem lub tabelą tymczasową. Dlatego ten sposób jest błędny.

To że procedura się utworzyła jest ok, jednak dopiero po puszczeniu na danych wyjdzie że podzapytania zwracają więcej niż jeden rekord

1

Usuwanie duplikatów... poszukaj bo na forum temat byl juz wielokrotnie poryszany

1

Zapytanie do usuniecia:

DELETE P
FROM 
    Products P
    inner join (select ProductName, SupplierID, min(ProductID) minID from Products group by ProductName, SupplierID) m 
    on p.ProductName = m.ProductName and p.SupplierID=m.SupplierID and p.ProductID > m.ProductID
0
Panczo napisał(a):

Na telefonie nie napiszę zapytania, normalnie nie robi się takich printow, ale jak rozumiem to w celach edukacyjnych.

Mógłbyś dokładniej wyjaśnić dlaczego normalnie nie robi się takich pritnów??
Poza tym twoje zapytanie rozwiązało mój problem. Dzięki bardzo.

1

Z punktu widzenia aplikacji taki print nie ma sensu, sama liczba usuniętych rekordów powie co się zadziało:

0 - nie ma duplikatów
większe od 0 - były duplikaty, w ilości usuniętych rekordów

1 użytkowników online, w tym zalogowanych: 0, gości: 1