• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

SQL - zliczanie rekordów z niedozwolonymi znakami.

0 głosów
109 wizyt
pytanie zadane 6 sierpnia 2018 w SQL, bazy danych przez Starkov Nowicjusz (140 p.)

Witam, 

mam pewien problem z którym nie mogą sobie poradzić. Mam dwie tabele: Contractors i Chars

W pierwszej znajduje się kolumna Name z ciągiem znaków będącym nazwą firmy. Rekordów jest kilkadziesiąt tysięcy.

W drugiej znajdują się dwie kolumny: Char i Allowed. W pierwszej znajduje się 90 wierszy wypełnionych różnymi pojedynczymi znakami (np. A, B, 0, %, ?, <, /), a w drugiej wartości 1 lub 0 (określają czy znak dozwolony lub niedozwolony). Musze przelecieć przez każdy rekord z tabeli Contactors z kolumny Name i sprawdzić w ilu znajduje się choć jeden znak z tabli Chars z wartością 0 (czyli policzyć w ilu nazwach firm znajduje się choć jeden niedozwolony znak).

Problem jest taki, że nie wiem nawet jak to za bardzo ugryźć, w SQL pisałem dotąd jedynie proste selecty i procedurki, rozumiem tylko że trzeba by rozbić każdy string na pojedyncze znaki ale nie wiem jakich do tego mechanizmów i funkcji SQLa użyć. Próbowałem z kursorami bo jest tam możliwość przetwarzania rekord po rekordzie i może coś w ten sposób (nie udało się), a może lepiej jakaś procedurę? Czy ktoś mógłby mnie naprowadzić na dobry trop i powiedzieć jak on by do tego podszedł? 

 

komentarz 7 sierpnia 2018 przez adrian17 Mędrzec (199,700 p.)
(inna sprawa, że to jakiś strasznie dziwny system, wygląda jak jakieś przekombinowane zadanie domowe)
komentarz 30 sierpnia 2018 przez ukasz112 Początkujący (390 p.)

Zgodzę się. Nie idzie tego optymalnie rozwiązać. Albo kursor albo sprawdzenie literka po literce, albo cross join albo jakieś pętle. Ogólnie rozwiązania nie sqlowe.

 

Zaproponowałbym zakorzystanie z PATINDEX() w przypadku T-SQL

 

SELECT
--	name,
--	PATINDEX('%[ĘŁ<>Ą]%',name) ,
	CASE 
		WHEN PATINDEX('%[ĘŁ<>Ą]%',name) = 0 THEN 'Dozwolone'
		WHEN PATINDEX('%[ĘŁ<>Ą]%',name) != 0THEN 'Niezodwolone' 
		ELSE null
	END AS Allowed,
		COUNT(*)
FROM contractors
GROUP BY 
	CASE 
		WHEN PATINDEX('%[ĘŁ<>Ą]%',name) = 0 THEN 'Dozwolone'
		WHEN PATINDEX('%[ĘŁ<>Ą]%',name) != 0THEN 'Niezodwolone' 
		ELSE null
	END 

 

 

komentarz 30 sierpnia 2018 przez ukasz112 Początkujący (390 p.)

Wymyśliłem! :)

 

create table contractors (id int identity(1,1), Name varchar(200))

insert into contractors(name) values ('Nazwa 1 ĄĘ')
insert into contractors(name) values ('Nazwa 2')
insert into contractors(name) values ('Nazwa 1 65')

create table chars (char char(1), allowed bit)
insert into chars(char, allowed)('6',0)
insert into chars(char, allowed)('Ą',0)
insert into chars(char, allowed)('Ę',0)

DECLARE @char varchar(max) = '';
SELECT @char += c.chars from chars c
SELECT  @char


SELECT
--	name,
--	PATINDEX('%'+@char+'%',name) ,
	CASE 
		WHEN PATINDEX('%'+@char+'%',name) = 0 THEN 'Dozwolone'
		WHEN PATINDEX('%'+@char+'%',name) != 0 THEN 'Niezodwolone' 
		ELSE null
	END AS Allowed,
		COUNT(*)
FROM contractors
GROUP BY 
	CASE 
		WHEN PATINDEX('%'+@char+'%',name) = 0 THEN 'Dozwolone'
		WHEN PATINDEX('%'+@char+'%',name) != 0 THEN 'Niezodwolone' 
		ELSE null
	END

 

2 odpowiedzi

0 głosów
odpowiedź 7 sierpnia 2018 przez areklipno Gaduła (3,420 p.)

poniżej napisałem Ci kod, który rozkłada wyrazy na litery

with slowa as (
select 'arek' as slowo
union all select 'szczebrzeszyn'
), litery as (
select substring(slowo,1,1) znaki
	,stuff(slowo,1,1,'') slowo
	,slowo wyraz
	, 1 as idw
from slowa

union all
	select substring(slowo,1,1) znaki
	,stuff(slowo,1,1,'') slowo
	, wyraz
	, idw+1 as idw
from litery
where len(slowo) > 0

)

select * 
from litery
order by wyraz

wystarczy teraz że zamiast tabeli słowa użyjesz swojej contractors, a tabele litery połączysz joinem z Twoją tabelą chars

0 głosów
odpowiedź 10 sierpnia 2018 przez Catalonya1992 Mądrala (5,000 p.)

Byłeś na dobrym tropie z tym kursorem. Tworzysz kursor select * from contractors. Później w pętli sprawdzasz dla każdej firmy czy ma znak niedozwolony, tzn.możesz stworzyć pętlę wewnętrzną (może być kursor select * from chars where allowed = '0');

W pętli wewnętrznej sprawdzasz czy nazwa firmy like '%'niedowzolony_znak_z_petli'%'. Jeśli tak to insert do jakiej tabeli i tam będzie lista tych błędnych nazw.

Kod:

declare

--lista wszystkich firm
cursor contractors is select * from contractors;

--lista niedozwolonych znaków
cursor chars is select * from chars where allowed = '0';

begin
    --pętla zewnętrzna
    for i in contractors
    loop
         --pętla wewnętrzna
        for x in chars
        loop
            --jesli nazwa ma niedozowlony znak
            if i.nazwa_firmy like '%'||x.char||'%' then
                insert into nowa_tabela values (i.nazwa_firmy);
                
                --zatwierdzenie inserta
                 commit;
            end if;
        --tu mozesz dodac tez sekcje obsługi wyjątków, żeby wiedziec jak wystapi jakis bład
        end loop;

    end loop;
    
end;

Daj znać czy zadziałało.

 

Podobne pytania

0 głosów
0 odpowiedzi 85 wizyt
0 głosów
2 odpowiedzi 121 wizyt
pytanie zadane 17 maja 2016 w SQL, bazy danych przez Dynamic Bywalec (2,490 p.)
0 głosów
1 odpowiedź 1,660 wizyt
Porady nie od parady
Wynikowy wygląd pytania, odpowiedzi czy komentarza, różni się od tego zaprezentowanego w edytorze postów. Stosuj więc funkcję Podgląd posta znajdującą się pod edytorem, aby upewnić się, czy na pewno ostateczny rezultat ci odpowiada.Podgląd posta

66,324 zapytań

113,061 odpowiedzi

239,218 komentarzy

46,589 pasjonatów

Przeglądających: 257
Pasjonatów: 8 Gości: 249

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...