Grzesiek [ www eRepublik com PL ]
Proszę o pomoc z zapytaniem SQL :)
Mam tabelę FORUM
- ForumID
- Name
- ParentID
- LastDate
- NumTopics
- NumPosts
oraz WATKI
- TopicID
- ForumID
- Message
I teraz mam dane:
- Główna - ForumID = 1
-- Polityka - ForumID = 2, ParentID = 1
--- Partie - ForumID = 3, ParentID = 2
---- Partia nr 1 - ForumID = 4, ParentID = 3
---- Partia nr 2 - ForumID = 5, ParentID = 3
I teraz np. chciałbym zaktualizować liczbę wątków/tematów w każdym forum - normalnie nie wiem jak się, do tego zabrać.
Najpierw Update ( SET NumTopics = SELECT COUNT(1) from WAKTI WHERE watki.ForumID = FORUM.ForumID
No dobra, a jak teraz zaktualizować fora nadrzędne? Da się to jakoś zapętlić w zapytaniu?
Zliczanie chyba odpada, ewentualnie sumowanie po wcześniejszym zliczeniu (powyżej), no nie?
Ale czy da się to do pętli wrzucić, bo nie chciałbym się ograniczać np. do 4 podrzędnych for.
albz74 [ Legend ]
A nie mógłbyś policzyć po prostu liczby wątków w podrzędnych forach, zsumować i zaktualizować kolejnym, osobnym zapytaniem ?
Takie rzeczy można triggerami też robić, aktualizować tylko najgłębiej zagnieżdżone fora a resztę serwer zrobi sam.
Grzesiek [ www eRepublik com PL ]
OK, czyli:
Na najgłębiej zagnieżdżonym forum zliczam wszystko - to działa.
Teraz sumowanie.
Chodzi o to, czy muszę za każdym razem pobrać ParentID i zaktualizować rekord o ForumID = ParentID czy da się to w pętlę jakoś wrzucić.
albz74 [ Legend ]
możesz przecież napisać w skrypcie kilka zapytań i kolejno zostaną wykonane.
Update najpierw najniższego poziomu, potem poziom wyżej itd.
Thrallik [ Konsul ]
Tu masz przykladowa petle ktora uaktualni wszystkie konta parent o ilosc watkow wsrod jego 'dzieci'. Dorzucilem kolumne ISPARENT do tabeli FORUM zeby troche ulatwic ten kod. Kolumna ta przyjmuje wartosci 0 albo 1
DECLARE @PARENTID INT
SET @PARENTID=(SELECT MIN(FORUMID) FROM FORUM WHERE ISPARENT=1)
WHILE EXISTS (SELECT FORUMID FROM FORUM WHERE ISPARENT=1 GROUP BY FORUMID HAVING @PARENTID <=MAX(FORUMID))
BEGIN
UPDATE FORUM SET NumPosts =
(SELECT SUM(QTY.ILOSCWATKOW) FROM FORUM F
INNER JOIN
(SELECT F1.FORUMID, COUNT(TopicID) AS ILOSCWATKOW FROM FORUM F1
INNER JOIN WATKI W
ON F1.ForumID=W.ForumID
GROUP BY F1.FORUMID
) QTY
ON F.FORUMID=QTY.FORUMID
WHERE PARENTID=@PARENTID)
WHERE FORUMID=@PARENTID
SET @PARENTID=(SELECT MIN(FORUMID) FROM FORUM WHERE ISPARENT=1 GROUP BY FORUMID HAVING FORUMID>@PARENTID)
END
Grzesiek [ www eRepublik com PL ]
Dzięki za pomoc - mam tylko dwa kłopoty.
Na wstępie - zmieniłem ten kod pod swoją sytuację:
ALTER PROCEDURE erepublik_dbuser.test2
AS
DECLARE @PARENTID INT
SET @PARENTID=(SELECT MIN(ForumID) FROM erepublik_forum_Forum WHERE ParentID != 0)
WHILE EXISTS (SELECT ForumID FROM erepublik_forum_Forum WHERE ParentID != 0 GROUP BY ForumID HAVING @PARENTID <= MAX(ForumID))
BEGIN
UPDATE erepublik_forum_Forum
SET NumPosts = (SELECT SUM(QTY.ILOSCWATKOW) FROM erepublik_forum_Forum F
INNER JOIN
(SELECT F1.ForumID, COUNT(TopicID) AS ILOSCWATKOW FROM erepublik_forum_Forum F1
INNER JOIN erepublik_forum_Topic W
ON F1.ForumID=W.ForumID
GROUP BY F1.ForumID
) QTY
ON F.ForumID=QTY.ForumID
WHERE ParentId=@PARENTID)
WHERE ParentId=@PARENTID
SET @PARENTID=(SELECT MIN(ForumID) FROM erepublik_forum_Forum WHERE ParentID != 0 GROUP BY ForumID HAVING ForumID > @PARENTID)
END
RETURN
Teraz, gdy wywołuję funkcję, otrzymuję non-stop komunikat:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Ponadto kod sumuje jedynie wątki dla każdej kategorii osobno, a ja bym chciał, by suma z kategorii Polityka = Partie + Partia nr 1 + Partia nr 2.
I jeszcze jedno - "Partie" też mogą być rekordy niekoniecznie podrzędne, tzn. na poziomie Partie kilka wątków, a reszta w Partia nr 1 i nr 2.
Grzesiek [ www eRepublik com PL ]
^
Grzesiek [ www eRepublik com PL ]
^
Grzesiek [ www eRepublik com PL ]
Nikt nie pomoże? :(
Grzesiek [ www eRepublik com PL ]
Sprawę zliczania rozwiązałem przy pomocy tej funkcji:
Ale teraz ...
Nie wiem jak napisać kod, który:
- pobierałby najnowszy rekord z tabeli erepublik_forum_Topic (to wiem, po dacie najnowszy) - pobiera datę, id
- aktualizowałby rekord w tabeli erepublik_forum_Forum, gdzie erepublik_forum_Forum.ForumID = erepublik_forum_Topi.ForumID
- aktualizowałby nadrzędne rekordy - z tym jest problem.
Trzeba to w pętlę wrzucić, funkcję pobierającą ID nadrzędnych for mam jako tako:
Tylko teraz jak zaktualizować te fora danymi z tej procedury:
1. Pobieram ID Forum
2. Procedura UpdateLastTopic aktualizuje mi forum o ID z 1.
3. Pobieram ID for nadrzędnych funkcją powyżej (GetForumsID)
4. Aktualizuję danymi z 2 fora z 3. Jak to zrobić?
Grzesiek [ www eRepublik com PL ]
^