J'ai un tableau Songs avec une colonne likes qui contient le nombre de likes envoyés par les utilisateurs. Chaque utilisateur envoie un booléen (1 ou 0) via une application C # qui s'ajoute à la colonne likes .
À propos de ma procédure:
Je veux savoir s'il existe un moyen plus efficace et plus court d'écrire la partie 1 de la fonction?
J'ai dû insérer manuellement «0» au lieu de NULL pour la première fois pour que la fonction fonctionne. Cela ne fonctionnait pas car la valeur initiale de la colonne Likes est NULL . Existe-t-il un moyen d'affecter la ligne pour la première fois lorsqu'elle contient NULL?
Pour la partie 2 de la fonction avec la table [Users_Likes_Songs] , je souhaite mettre à jour si l'utilisateur envoie un like (true = 1) ou l'a supprimé (false = 0).
Comment puis-je mettre à jour ce tableau pour la première fois lorsque les utilisateurs «j'aime» doivent avoir la valeur «1», lorsque ses lignes sont complètement vides?
Je vous remercie beaucoup si vous pouvez m'aider.
La procédure:
CREATE PROCEDURE Songs_Likes
@User_ID INT,
@SongID INT,
@Song_like BIT
AS
BEGIN
--- part 1 of the function
IF (@Song_like = 1)
BEGIN
UPDATE [Songs]
SET [Likes] = [Likes] + @Song_like
WHERE [Song_ID] = @SongID
END
IF (@Song_like = 0)
BEGIN
UPDATE [Songs]
SET [Likes] = [Likes] - 1
WHERE [Song_ID] = @SongID
END
--- part 2 of the function with the second table
UPDATE [Users_Likes_Songs]
SET [LikeSong] = @Song_like
WHERE ([UserID] = @User_ID) AND ([SongID] = @SongID)
END
3 Réponses :
Vous pouvez essayer cette requête dans votre procédure
UPDATE [songs] SET [likes] = Isnull ([likes], 0) + ( CASE WHEN @Song_like THEN 1 ELSE -1 END) WHERE [song_id] = @SongID
Il y a un erratum dans votre code: "ESLE" -> "ELSE". De plus, COALESCE est plus recommandé que ISNULL, tout comme la norme ANSII
Pour 1) c'est un peu plus clair, plus court et un peu plus efficace.
IF NOT EXISTS (SELECT 1
FROM [Users_Likes_Songs]
WHERE [UserID] = @User_ID
AND [SongID] = @SongID)
INSERT INTO [Users_Likes_Songs] (User_ID, SongID, [LikeSong])
VALUES (@User_ID, @SongID, @Song_like)
ELSE
UPDATE [Users_Likes_Songs]
SET [LikeSong] = @Song_like WHERE ([UserID] = @User_ID) AND ([SongID] = @SongID)
Pour la deuxième partie, vous pouvez faire quelque chose comme ceci:
UPDATE [Songs]
SET [Likes] = COALESCE([Likes], 0) + CASE WHEN @Song_like = 1 THEN 1
WHEN @Song_like = 0 THEN -1
ELSE 0 END
WHERE [Song_ID] = @SongID;
J'ai mis à jour ma deuxième partie de la question, pouvez-vous la regarder? Je veux savoir si vous avez bien compris votre réponse.
Merci, il suffit de modifier votre réponse avec moins ')' '(' as - (SELECT 1 FROM [Users_Likes_Songs] WHERE [UserID] = @User_ID AND [SongID] = @SongID)
Ah, oui ... il y avait quelques déroutants () et un manquant). Corrigé dans ma réponse pour référence future. Merci d'avoir partagé !!!
Je pense que la meilleure méthode serait de changer votre design pour calculer les likes et avoir une table qui stocke les likes pour chaque utilisateur. En termes simples, quelque chose comme:
USE Sandbox;
GO
CREATE SCHEMA music;
GO
CREATE TABLE music.song (SongID int IDENTITY(1,1),
Artist nvarchar(50) NOT NULL,
Title nvarchar(50) NOT NULL,
ReleaseDate date);
CREATE TABLE music.[User] (UserID int IDENTITY(1,1),
[Login] nvarchar(128));
CREATE TABLE music.SongLike (LikeID bigint IDENTITY(1,1),
SongID int,
UserID int,
Liked bit);
CREATE UNIQUE NONCLUSTERED INDEX UserLike ON music.SongLike(SongID, UserID); --Stops multiple likes
GO
--To add a LIKE you can then have a SP like:
CREATE PROC music.AddLike @SongID int, @UserID int, @Liked bit AS
BEGIN
IF EXISTS (SELECT 1 FROM music.SongLike WHERE UserID = @UserID AND SongID = @SongID) BEGIN
UPDATE music.SongLike
SET Liked = @Liked
WHERE UserID = @UserID
AND SongID = @SongID
END ELSE BEGIN
INSERT INTO music.SongLike (SongID,
UserID,
Liked)
VALUES (@SongID, @UserID, @Liked);
END
END
GO
--And, if you want the number of likes:
CREATE VIEW music.SongLikes AS
SELECT S.Artist,
S.Title,
S.ReleaseDate,
COUNT(CASE SL.Liked WHEN 1 THEN 1 END) AS Likes
FROM music.Song S
JOIN music.SongLike SL ON S.SongID = SL.SongID
GROUP BY S.Artist,
S.Title,
S.ReleaseDate;
GO
J'ajouterais une contrainte (FK) pour la référence de table SongsLikes le songID.
Il y a plusieurs index et contraintes dont il a besoin, @Sami. Ce n'était que l'essentiel. Je ne fais pas tout le travail pour l'OP :)
Pourquoi avez-vous besoin de stocker le nombre de J'aime dans le tableau
Chansons? Vous pouvez toujours le calculer simplement à partir de la tableUsers_Likes_Songs.En ce qui concerne votre commentaire B, pourquoi ne pas définir la valeur
DEFAULTdeLikessur 0, au lieu deNULL? Idéalement, cependant, je calculerais en fait le nombre de likes comme une valeur calculée. Le stockage dans une table peut facilement se terminer par une valeur incorrecte; surtout avec des choses comme les conditions de course.@HoneyBadger, c'est une bonne idée, mais pour le projet de démonstration, je dois insérer de «faux» likes sans utilisateur réel.
@ sup.DR Je dirais que vous ne pouvez pas avoir de likes sans utilisateurs, même pour une démo. Si vous avez besoin de faire une démonstration, créez de faux utilisateurs et faites-leur aimer et ne pas aimer les chansons.