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
DEFAULT
deLikes
sur 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.