MS SQL Indywidualny licznik dla danego ID

MS SQL Indywidualny licznik dla danego ID
sssokol
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 lat
  • Lokalizacja:Poznań
  • Postów:19
0

Witam,
poszukuję rozwiązania do poniższego zadania.
Chcę stworzyć licznik dla danego Id oparty o WARTOŚĆ.
Licznik ma się zerować co 4 lub jeśli wartość jest inna niż 10, jak w załączonym przykładzie.
W tabeli jest kilkaset ID i dla każdego ID licznik musi działać osobno.
Czy ktoś ma jakiś pomysł?

FLTiaz.jpg

abrakadaber
abrakadaber
  • Rejestracja:ponad 12 lat
  • Ostatnio:7 miesięcy
  • Postów:6610
0

trigger, ale i tak będzie problem jak będzie dużo insertów w krótkim czasie. Aby to było w 100% pewne to trzeba by mieć dodatkową tabelkę, a w niej id i aktualny_licznik. Pobierać z blokowaniem stan licznika dla danego id, wyliczać nową wartość, wstawiać rekord i updejtować ten w tabelce z licznikiem


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
PA
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 4 godziny
  • Postów:3865
0

Która wersja SQL Servera?
Co determinuje kolejność?

sssokol
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 lat
  • Lokalizacja:Poznań
  • Postów:19
0
Panczo napisał(a):

Która wersja SQL Servera?
Co determinuje kolejność?

2014, kolejność determinuje data

sssokol
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 lat
  • Lokalizacja:Poznań
  • Postów:19
0

Jeśli to coś pomoże to licznik może się zerować tylko wtedy kiedy wartość jest różna od 10.

CM
  • Rejestracja:około 9 lat
  • Ostatnio:ponad 6 lat
  • Lokalizacja:Warszawa
  • Postów:118
0

Potrzebujesz tego w czasie rzeczywistym? Jeżeli nie, to co jakiś czas możesz robić update na kolumnie i problem staje się całkiem prosty do rozwiązania.

sssokol
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 lat
  • Lokalizacja:Poznań
  • Postów:19
0

To jest tabela, która jest zasilana danymi codziennie.
Codziennie wpada kilkadziesiąt wierszy danych. Liczba wierszy cały czas rośnie.
W pewnym momencie osiagnie kilka tysięcy wierszy więc update'owanie tej tabeli przy kilkuset ID nie tym o czym marze :)
wolałbym ustawić tutaj automat.

hyde
Kilkaset ID, kilka tysięcy wierszy to dla bazy klasy SQL Server czy Oracle są ilości które wciąga nosem i nawet nie zauważa.
CM
  • Rejestracja:około 9 lat
  • Ostatnio:ponad 6 lat
  • Lokalizacja:Warszawa
  • Postów:118
0

Możesz stworzyć joba, który będzie codziennie robił update na tabeli. Nie korzystam z MS serwera, ale ktoś na pewno Ci podpowie jak to zrobić.

sssokol
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 lat
  • Lokalizacja:Poznań
  • Postów:19
0

To też jakiś pomysł, potrafię zrobić joba. dzięki.

PA
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 4 godziny
  • Postów:3865
0

A jaka jest pewność ze zawsze dostajesz większe daty, co w przypadku gdy ktoś wprowadzi daty wczesniejsze i będzie to wymagalo zmiany w innych rekordach?
Jak tabela jest zasilana?

sssokol
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 lat
  • Lokalizacja:Poznań
  • Postów:19
0

To jest zrzut z CRMa po wizytach handlowców. Data wstecz nie jest możliwa.

PA
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 4 godziny
  • Postów:3865
0

Not skoro to jest zrzut z jakiegoś systemu, to jaki masz wpływ na wykonanie tego importu.
Mnie się wydaje, że najrozsądniej jest paczkę danych dać do jakiejś tempowej tabeli, wyliczyć te id i wrzucić do tabeli docelowej.

Chyba, że na docelowej tabeli działają inni użytkownicy i dodają usuwają dane. Z ciekawości, do czego służyć ma takie numerowanie?

p.s. jak słyszę że ktoś mi mówi, że coś jest niemożliwe to na pewno się przydarzy ;)

sssokol
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 lat
  • Lokalizacja:Poznań
  • Postów:19
0

Numerowanie jest potrzebne do weryfikowania poprawnosci podpisanego kontraktu pomiedzy moja firma a klientami. Jezeli klient podczas czterech wizyt przedstawiciela z rzędu spelni warunki kontraktu to jest mu wyplacany bonus. Bonus jest wyplacany ci 4 poprawne wizyty. U danego klienta jest jedna wizyta w tygodniu. Jesli na ktorejs z wizyt nie spelnia warunkow kontraktu to licznik wraca do 1.

DE
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 3 lata
0
PA
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 4 godziny
  • Postów:3865
0

Pytanie czy faktycznie potrzebujesz numerku przy kazdym rekordzie/wizycie, czy wystarczy informacja w ramach id ile tych bonusów powinno być?

sssokol
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 lat
  • Lokalizacja:Poznań
  • Postów:19
0

Nie potrzebuje numerka :)

PA
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 4 godziny
  • Postów:3865
1

No to skoro nie potrzebujesz numerka, to wystarczy sprawdzić ile rekordów jest pomiędzy zmianami i podzielić przez 4 bez reszty, ale pokolei

Dla twoich danych

Kopiuj
CREATE TABLE T
    ([id] int, [wartosc] int, [data] int)
;
    
INSERT INTO T
    ([id], [wartosc], [data])
VALUES
    (354, 10,1),
    (354, 10,2),
    (354, 10, 3),
    (354, 10, 4),
    (354, 10, 5),
    (354, 10, 6),
    (354, 8,  7),
    (354, 10, 8),
    (354, 10, 9),
    (354, 10, 10),
    (354, 10, 11)

Date zrobiłem int, ale to bez znaczenia bo ta kolumna służy tylko do sprawdzenia kolejności.
Pierwsze co to musimy zidentyfikować początek i koniec przedziałów czwórek, w naszym przypadku to są dwa przedziały:
data: 1-6 i 7-11
Do tego posłuży zapytanie

Kopiuj
select 
	* ,
	CASE 
		WHEN (LAG(WARTOSC, 1,-1) OVER (PARTITION BY ID ORDER BY DATA) <> WARTOSC AND WARTOSC <> 10)
			OR  LAG(WARTOSC, 1,-1) OVER (PARTITION BY ID ORDER BY DATA) = -1 THEN 
				'START' 
		WHEN LEAD(WARTOSC, 1,0) OVER (PARTITION BY ID ORDER BY DATA) <> 10 THEN 
			'STOP' 
		ELSE '' 
	END AS STARTSTOP
	,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DATA) R 
from 
	t

Które da w wyniku:

id wartosc data STARTSTOP R
354 10 1 START 1
354 10 2 2
354 10 3 3
354 10 4 4
354 10 5 5
354 10 6 STOP 6
354 8 7 START 7
354 10 8 8
354 10 9 9
354 10 10 10
354 10 11 STOP 11

Teraz potrzebujemy tylko wierszy z wpisami w kolumnie startstop:

id wartosc data STARTSTOP R
354 10 1 START 1
354 10 6 STOP 6
354 8 7 START 7
354 10 11 STOP 11

Pozostaje matematyka: czyli dla każdego wpisu stop, odejmujemy od r poprzednie r dodajmy 1 i dzielimy bez reszty przez 4:

Kopiuj
select 
	*
	,case when startstop = 'stop' then 
		cast(r+1-LAG(r, 1,0) OVER (PARTITION BY ID ORDER BY DATA) as integer)/4
	else
		0
	end iloscbonusow
from f

Wynik

id wartosc data STARTSTOP R iloscbonusow
354 10 1 START 1 0
354 10 6 STOP 6 1
354 8 7 START 7 0
354 10 11 STOP 11 1

Reszta to podsumowanie kolumny iloscbonusow
Całe rozwiązanie:

Kopiuj
WITH cteT as (
select 
	* ,
	CASE 
		WHEN (LAG(WARTOSC, 1,-1) OVER (PARTITION BY ID ORDER BY DATA) <> WARTOSC AND WARTOSC <> 10)
			OR  LAG(WARTOSC, 1,-1) OVER (PARTITION BY ID ORDER BY DATA) = -1 THEN 
				'START' 
		WHEN LEAD(WARTOSC, 1,0) OVER (PARTITION BY ID ORDER BY DATA) <> 10 THEN 
			'STOP' 
		ELSE '' 
	END AS STARTSTOP
	,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DATA) R 
from 
	t)
, f as (
select 
	* 
from 
	cteT
where 
	startstop in ('start','stop')
)

SELECT
	ID
	,SUM(ILOSCBONUSOW) B
FROM (
	select 
		id
		,case when startstop = 'stop' then 
			cast(r+1-LAG(r, 1,0) OVER (PARTITION BY ID ORDER BY DATA) as integer)/4
		else
			0
		end iloscbonusow
	from 
		f) DT
GROUP BY
	ID

Wynik:

ID B
354 2
sssokol
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 lat
  • Lokalizacja:Poznań
  • Postów:19
0

Dostałem za zadanie rozwiązać to za pomocą kursora.

Stworzyłem kursor ale licznik nie zeruje mi się kiedy zmienia się ID klienta. Czy ktoś może mi powiedzieć gdzie popełniłem błąd?

===============================================================================================================
DECLARE @row int
DECLARE @kli int
DECLARE @poprzedni_kli int
DECLARE kursor SCROLL cursor for
SELECT rowid, rep_id FROM crm_target_kampanie WHERE campaign = 'akcja_lato_licznik' and target=10 ORDER BY rowid
DECLARE @counter int=1

Open kursor

FETCH NEXT FROM kursor
INTO @row, @kli
WHILE @@FETCH_STATUS=0
BEGIN

SET @poprzedni_kli=@kli

IF @poprzedni_kli=@kli
BEGIN 
update crm_target_kampanie set attrib1=@counter WHERE campaign = 'akcja_lato_licznik' and rep_id=@kli and rowid=@row
SET @counter=@counter+1
END

ELSE

BEGIN
SET @counter=1 
update crm_target_kampanie set attrib1=@counter WHERE campaign = 'akcja_lato_licznik' and rep_id=@kli and rowid=@row
SET @counter=@counter+1
END

FETCH NEXT FROM kursor 
INTO @row, @kli 

END
CLOSE kursor
DEALLOCATE kursor

=================================================================================================================

licznik

PA
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 4 godziny
  • Postów:3865
0

A jak ci ma się zerować, skoro @poprzedni_kli=@kli zawsze będzie prawdziwe, bo PRZED porównaniem przypisujesz bieżącą wartość do poprzedniej?

sssokol
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 lat
  • Lokalizacja:Poznań
  • Postów:19
0
Panczo napisał(a):

A jak ci ma się zerować, skoro @poprzedni_kli=@kli zawsze będzie prawdziwe, bo PRZED porównaniem przypisujesz bieżącą wartość do poprzedniej?

Domyśliłem się, że to nie działa ale właśnie nie wiem w którym miejscu w takim razie umieścić "SET @poprzedni_kli=@kli"

PA
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 4 godziny
  • Postów:3865
1

Najprościej wtedy kiedy się zmienia...

Kopiuj
DECLARE @row int
DECLARE @kli int
DECLARE @poprzedni_kli int=-1
DECLARE kursor SCROLL cursor for
SELECT rowid, rep_id FROM crm_target_kampanie WHERE campaign = 'akcja_lato_licznik' and target=10 ORDER BY rowid
DECLARE @counter int=1

Open kursor
FETCH NEXT FROM kursor INTO @row, @kli 

WHILE @@FETCH_STATUS=0
	BEGIN
		IF @poprzedni_kli=@kli
			BEGIN 
				update crm_target_kampanie set attrib1=@counter WHERE campaign = 'akcja_lato_licznik' and rep_id=@kli and rowid=@row
				SET @counter=@counter+1
			END
		ELSE
			BEGIN
				SET @poprzedni_kli=@kli
				SET @counter=1 
				update crm_target_kampanie set attrib1=@counter WHERE campaign = 'akcja_lato_licznik' and rep_id=@kli and rowid=@row
				SET @counter=@counter+1
			END
		FETCH NEXT FROM kursor INTO @row, @kli 
	END

CLOSE kursor
DEALLOCATE kursor

Dużo czytelniej jest jednak uprościć samą pętle:

Kopiuj
WHILE @@FETCH_STATUS=0
BEGIN

	IF @poprzedni_kli<>@kli
	BEGIN
		SET @poprzedni_kli=@kli
		SET @counter=1 
	END		

	update crm_target_kampanie set attrib1=@counter WHERE campaign = 'akcja_lato_licznik' and rep_id=@kli and rowid=@row			

	SET @counter=@counter+1

	FETCH NEXT FROM kursor INTO @row, @kli 

END


edytowany 3x, ostatnio: Panczo
sssokol
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 6 lat
  • Lokalizacja:Poznań
  • Postów:19
0

Wielkie dzięki :)

druga opcja jednak nie działa - nie zeruje licznika przy nowym kliencie

PA
skoro pierwsza działa to druga, też musi... Zwróć uwagę, ze @poprzedni_kli ma w deklaracji domyslnie -1
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)