From 655a23a2a8e6dbd41027cf3a36e0c2b438aa34b0 Mon Sep 17 00:00:00 2001 From: Dave Walker Date: Thu, 30 Nov 2023 15:51:35 +0000 Subject: [PATCH] Implement the retailer statistics report --- docker/api/Dockerfile | 4 +- sql/Summarise By Retailer.sql | 23 ++ .../Controllers/ReportsController.cs | 21 + .../MusicCatalogue.Api.csproj | 6 +- ...31130153046_RetailerStatistics.Designer.cs | 376 ++++++++++++++++++ .../20231130153046_RetailerStatistics.cs | 38 ++ .../MusicCatalogueDbContextModelSnapshot.cs | 24 ++ .../MusicCatalogue.Data.csproj | 4 +- .../MusicCatalogueDbContext.cs | 1 + .../Interfaces/IMusicCatalogueFactory.cs | 1 + .../MusicCatalogue.Entities.csproj | 4 +- .../Reporting/RetailerStatistics.cs | 26 ++ .../Factory/MusicCatalogueFactory.cs | 5 + .../MusicCatalogue.Logic.csproj | 6 +- .../Sql/RetailerStatistics.sql | 23 ++ .../MusicCatalogue.LookupTool.csproj | 6 +- 16 files changed, 554 insertions(+), 14 deletions(-) create mode 100644 sql/Summarise By Retailer.sql create mode 100644 src/MusicCatalogue.Data/Migrations/20231130153046_RetailerStatistics.Designer.cs create mode 100644 src/MusicCatalogue.Data/Migrations/20231130153046_RetailerStatistics.cs create mode 100644 src/MusicCatalogue.Entities/Reporting/RetailerStatistics.cs create mode 100644 src/MusicCatalogue.Logic/Sql/RetailerStatistics.sql diff --git a/docker/api/Dockerfile b/docker/api/Dockerfile index 459abe2..4fcd743 100644 --- a/docker/api/Dockerfile +++ b/docker/api/Dockerfile @@ -1,4 +1,4 @@ FROM mcr.microsoft.com/dotnet/core/aspnet:latest -COPY musiccatalogue.api-1.22.0.0 /opt/musiccatalogue.api-1.22.0.0 -WORKDIR /opt/musiccatalogue.api-1.22.0.0/bin +COPY musiccatalogue.api-1.23.0.0 /opt/musiccatalogue.api-1.23.0.0 +WORKDIR /opt/musiccatalogue.api-1.23.0.0/bin ENTRYPOINT [ "./MusicCatalogue.Api" ] diff --git a/sql/Summarise By Retailer.sql b/sql/Summarise By Retailer.sql new file mode 100644 index 0000000..a7d7584 --- /dev/null +++ b/sql/Summarise By Retailer.sql @@ -0,0 +1,23 @@ +WITH RETAILER_SPEND ( Id, Name, IsWishListItem, Spend ) AS +( + SELECT r.Id, + r.Name, + IFNULL( al.IsWishListItem, 0), + SUM( IFNULL( al.Price, 0 ) ) + FROM ALBUMS al + LEFT OUTER JOIN RETAILERS r ON r.Id = al.RetailerId + GROUP BY r.Id, r.Name, IFNULL( al.IsWishListItem, 0) +) +SELECT RANK() OVER ( ORDER BY rsp.Name ASC ) AS "Id", + rsp.Name, + COUNT( DISTINCT a.Id ) AS "Artists", + COUNT( DISTINCT al.Id ) AS "Albums", + COUNT( DISTINCT t.Id ) AS "Tracks", + rsp.Spend +FROM RETAILER_SPEND rsp +INNER JOIN ALBUMS al ON al.RetailerId = rsp.Id +INNER JOIN TRACKS t ON t.AlbumId = al.Id +INNER JOIN ARTISTS a ON a.Id = al.ArtistId +WHERE rsp.IsWishListItem = 0 +AND IFNULL( al.IsWishListItem, 0 ) = 0 +GROUP BY rsp.Name; diff --git a/src/MusicCatalogue.Api/Controllers/ReportsController.cs b/src/MusicCatalogue.Api/Controllers/ReportsController.cs index 5bb0af1..ee8b7dd 100644 --- a/src/MusicCatalogue.Api/Controllers/ReportsController.cs +++ b/src/MusicCatalogue.Api/Controllers/ReportsController.cs @@ -116,5 +116,26 @@ public async Task>> GetMonthlySpendingReportAsyn // Convert to a list and return the results return results.ToList(); } + + /// + /// Generate the retailer statistics report + /// + /// + /// + [HttpGet] + [Route("retailers/{wishlist}")] + public async Task>> GetRetailerStatisticsReportAsync(bool wishlist) + { + // Get the report content + var results = await _factory.RetailerStatistics.GenerateReportAsync(wishlist, 1, int.MaxValue); + + if (!results.Any()) + { + return NoContent(); + } + + // Convert to a list and return the results + return results.ToList(); + } } } diff --git a/src/MusicCatalogue.Api/MusicCatalogue.Api.csproj b/src/MusicCatalogue.Api/MusicCatalogue.Api.csproj index 6940e42..d55e5b1 100644 --- a/src/MusicCatalogue.Api/MusicCatalogue.Api.csproj +++ b/src/MusicCatalogue.Api/MusicCatalogue.Api.csproj @@ -2,9 +2,9 @@ net7.0 - 1.22.0.0 - 1.22.0.0 - 1.22.0 + 1.23.0.0 + 1.23.0.0 + 1.23.0 enable enable diff --git a/src/MusicCatalogue.Data/Migrations/20231130153046_RetailerStatistics.Designer.cs b/src/MusicCatalogue.Data/Migrations/20231130153046_RetailerStatistics.Designer.cs new file mode 100644 index 0000000..bb77560 --- /dev/null +++ b/src/MusicCatalogue.Data/Migrations/20231130153046_RetailerStatistics.Designer.cs @@ -0,0 +1,376 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MusicCatalogue.Data; + +#nullable disable + +namespace MusicCatalogue.Data.Migrations +{ + [DbContext(typeof(MusicCatalogueDbContext))] + [Migration("20231130153046_RetailerStatistics")] + partial class RetailerStatistics + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.11"); + + modelBuilder.Entity("MusicCatalogue.Entities.Database.Album", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("Id"); + + b.Property("ArtistId") + .HasColumnType("INTEGER") + .HasColumnName("ArtistId"); + + b.Property("CoverUrl") + .HasColumnType("TEXT") + .HasColumnName("CoverUrl"); + + b.Property("GenreId") + .HasColumnType("INTEGER") + .HasColumnName("GenreId"); + + b.Property("IsWishListItem") + .HasColumnType("INTEGER"); + + b.Property("Price") + .HasColumnType("TEXT") + .HasColumnName("Price"); + + b.Property("Purchased") + .HasColumnType("TEXT") + .HasColumnName("Purchased"); + + b.Property("Released") + .HasColumnType("INTEGER") + .HasColumnName("Released"); + + b.Property("RetailerId") + .HasColumnType("INTEGER") + .HasColumnName("RetailerId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("Title"); + + b.HasKey("Id"); + + b.HasIndex("ArtistId"); + + b.HasIndex("GenreId"); + + b.HasIndex("RetailerId"); + + b.ToTable("ALBUMS", (string)null); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Database.Artist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("Id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("Name"); + + b.Property("SearchableName") + .HasColumnType("TEXT") + .HasColumnName("SearchableName"); + + b.HasKey("Id"); + + b.ToTable("ARTISTS", (string)null); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Database.Genre", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("Id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("Name"); + + b.HasKey("Id"); + + b.ToTable("GENRES", (string)null); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Database.JobStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("id"); + + b.Property("End") + .HasColumnType("DATETIME") + .HasColumnName("end"); + + b.Property("Error") + .HasColumnType("TEXT") + .HasColumnName("error"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.Property("Parameters") + .HasColumnType("TEXT") + .HasColumnName("parameters"); + + b.Property("Start") + .HasColumnType("DATETIME") + .HasColumnName("start"); + + b.HasKey("Id"); + + b.ToTable("JOB_STATUS", (string)null); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Database.Retailer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("Id"); + + b.Property("Address1") + .HasColumnType("TEXT"); + + b.Property("Address2") + .HasColumnType("TEXT"); + + b.Property("Country") + .HasColumnType("TEXT"); + + b.Property("County") + .HasColumnType("TEXT"); + + b.Property("Latitude") + .HasColumnType("TEXT"); + + b.Property("Longitude") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("Name"); + + b.Property("PostCode") + .HasColumnType("TEXT"); + + b.Property("Town") + .HasColumnType("TEXT"); + + b.Property("WebSite") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("RETAILERS", (string)null); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Database.Track", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("Id"); + + b.Property("AlbumId") + .HasColumnType("INTEGER") + .HasColumnName("AlbumId"); + + b.Property("Duration") + .HasColumnType("INTEGER") + .HasColumnName("Duration"); + + b.Property("Number") + .HasColumnType("INTEGER") + .HasColumnName("Number"); + + b.Property("Purchased") + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("Title"); + + b.HasKey("Id"); + + b.HasIndex("AlbumId"); + + b.ToTable("TRACKS", (string)null); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Database.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("id"); + + b.Property("Password") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("Password"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.ToTable("USER", (string)null); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Reporting.ArtistStatistics", b => + { + b.Property("Albums") + .HasColumnType("INTEGER"); + + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Spend") + .HasColumnType("TEXT"); + + b.Property("Tracks") + .HasColumnType("INTEGER"); + + b.ToTable("ArtistStatistics"); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Reporting.GenreStatistics", b => + { + b.Property("Albums") + .HasColumnType("INTEGER"); + + b.Property("Artists") + .HasColumnType("INTEGER"); + + b.Property("Genre") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("Spend") + .HasColumnType("TEXT"); + + b.Property("Tracks") + .HasColumnType("INTEGER"); + + b.ToTable("GenreStatistics"); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Reporting.MonthlySpend", b => + { + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("Month") + .HasColumnType("INTEGER"); + + b.Property("Spend") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.ToTable("MonthlySpend"); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Reporting.RetailerStatistics", b => + { + b.Property("Albums") + .HasColumnType("INTEGER"); + + b.Property("Artists") + .HasColumnType("INTEGER"); + + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Spend") + .HasColumnType("TEXT"); + + b.Property("Tracks") + .HasColumnType("INTEGER"); + + b.ToTable("RetailerStatistics"); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Database.Album", b => + { + b.HasOne("MusicCatalogue.Entities.Database.Artist", null) + .WithMany("Albums") + .HasForeignKey("ArtistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MusicCatalogue.Entities.Database.Genre", "Genre") + .WithMany() + .HasForeignKey("GenreId"); + + b.HasOne("MusicCatalogue.Entities.Database.Retailer", "Retailer") + .WithMany() + .HasForeignKey("RetailerId"); + + b.Navigation("Genre"); + + b.Navigation("Retailer"); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Database.Track", b => + { + b.HasOne("MusicCatalogue.Entities.Database.Album", null) + .WithMany("Tracks") + .HasForeignKey("AlbumId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Database.Album", b => + { + b.Navigation("Tracks"); + }); + + modelBuilder.Entity("MusicCatalogue.Entities.Database.Artist", b => + { + b.Navigation("Albums"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/MusicCatalogue.Data/Migrations/20231130153046_RetailerStatistics.cs b/src/MusicCatalogue.Data/Migrations/20231130153046_RetailerStatistics.cs new file mode 100644 index 0000000..37a3fce --- /dev/null +++ b/src/MusicCatalogue.Data/Migrations/20231130153046_RetailerStatistics.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System.Diagnostics.CodeAnalysis; + +#nullable disable + +namespace MusicCatalogue.Data.Migrations +{ + /// + public partial class RetailerStatistics : Migration + { + [ExcludeFromCodeCoverage] + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "RetailerStatistics", + columns: table => new + { + Name = table.Column(type: "TEXT", nullable: false), + Artists = table.Column(type: "INTEGER", nullable: true), + Albums = table.Column(type: "INTEGER", nullable: true), + Tracks = table.Column(type: "INTEGER", nullable: true), + Spend = table.Column(type: "TEXT", nullable: true), + Id = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "RetailerStatistics"); + } + } +} diff --git a/src/MusicCatalogue.Data/Migrations/MusicCatalogueDbContextModelSnapshot.cs b/src/MusicCatalogue.Data/Migrations/MusicCatalogueDbContextModelSnapshot.cs index 5231dca..4eaea1d 100644 --- a/src/MusicCatalogue.Data/Migrations/MusicCatalogueDbContextModelSnapshot.cs +++ b/src/MusicCatalogue.Data/Migrations/MusicCatalogueDbContextModelSnapshot.cs @@ -306,6 +306,30 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("MonthlySpend"); }); + modelBuilder.Entity("MusicCatalogue.Entities.Reporting.RetailerStatistics", b => + { + b.Property("Albums") + .HasColumnType("INTEGER"); + + b.Property("Artists") + .HasColumnType("INTEGER"); + + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Spend") + .HasColumnType("TEXT"); + + b.Property("Tracks") + .HasColumnType("INTEGER"); + + b.ToTable("RetailerStatistics"); + }); + modelBuilder.Entity("MusicCatalogue.Entities.Database.Album", b => { b.HasOne("MusicCatalogue.Entities.Database.Artist", null) diff --git a/src/MusicCatalogue.Data/MusicCatalogue.Data.csproj b/src/MusicCatalogue.Data/MusicCatalogue.Data.csproj index bee13e5..63a2782 100644 --- a/src/MusicCatalogue.Data/MusicCatalogue.Data.csproj +++ b/src/MusicCatalogue.Data/MusicCatalogue.Data.csproj @@ -5,7 +5,7 @@ enable enable MusicCatalogue.Data - 1.20.0.0 + 1.21.0.0 Dave Walker Copyright (c) Dave Walker 2023 Dave Walker @@ -17,7 +17,7 @@ https://github.com/davewalker5/MusicCatalogue MIT false - 1.20.0.0 + 1.21.0.0 diff --git a/src/MusicCatalogue.Data/MusicCatalogueDbContext.cs b/src/MusicCatalogue.Data/MusicCatalogueDbContext.cs index 56f22ef..5f3b651 100644 --- a/src/MusicCatalogue.Data/MusicCatalogueDbContext.cs +++ b/src/MusicCatalogue.Data/MusicCatalogueDbContext.cs @@ -18,6 +18,7 @@ public class MusicCatalogueDbContext : DbContext public virtual DbSet GenreStatistics { get; set; } public virtual DbSet ArtistStatistics { get; set; } public virtual DbSet MonthlySpend { get; set; } + public virtual DbSet RetailerStatistics { get; set; } public MusicCatalogueDbContext(DbContextOptions options) : base(options) { diff --git a/src/MusicCatalogue.Entities/Interfaces/IMusicCatalogueFactory.cs b/src/MusicCatalogue.Entities/Interfaces/IMusicCatalogueFactory.cs index d7a2dcc..b73630d 100644 --- a/src/MusicCatalogue.Entities/Interfaces/IMusicCatalogueFactory.cs +++ b/src/MusicCatalogue.Entities/Interfaces/IMusicCatalogueFactory.cs @@ -20,5 +20,6 @@ public interface IMusicCatalogueFactory IWishListBasedReport GenreStatistics { get; } IWishListBasedReport ArtistStatistics { get; } IWishListBasedReport MonthlySpend { get; } + IWishListBasedReport RetailerStatistics { get; } } } \ No newline at end of file diff --git a/src/MusicCatalogue.Entities/MusicCatalogue.Entities.csproj b/src/MusicCatalogue.Entities/MusicCatalogue.Entities.csproj index b2ced07..946b5ff 100644 --- a/src/MusicCatalogue.Entities/MusicCatalogue.Entities.csproj +++ b/src/MusicCatalogue.Entities/MusicCatalogue.Entities.csproj @@ -5,7 +5,7 @@ enable enable MusicCatalogue.Entities - 1.20.0.0 + 1.21.0.0 Dave Walker Copyright (c) Dave Walker 2023 Dave Walker @@ -17,7 +17,7 @@ https://github.com/davewalker5/MusicCatalogue MIT false - 1.20.0.0 + 1.21.0.0 diff --git a/src/MusicCatalogue.Entities/Reporting/RetailerStatistics.cs b/src/MusicCatalogue.Entities/Reporting/RetailerStatistics.cs new file mode 100644 index 0000000..8afe09d --- /dev/null +++ b/src/MusicCatalogue.Entities/Reporting/RetailerStatistics.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore; +using MusicCatalogue.Entities.Attributes; +using System.Diagnostics.CodeAnalysis; + +namespace MusicCatalogue.Entities.Reporting +{ + [Keyless] + [ExcludeFromCodeCoverage] + public class RetailerStatistics : ReportEntityBase + { + [Export("Name", 1)] + public string Name { get; set; } = ""; + + [Export("Artists", 2)] + public int? Artists { get; set; } + + [Export("Albums", 3)] + public int? Albums { get; set; } + + [Export("Tracks", 4)] + public int? Tracks { get; set; } + + [Export("Spend", 5)] + public decimal? Spend { get; set; } + } +} diff --git a/src/MusicCatalogue.Logic/Factory/MusicCatalogueFactory.cs b/src/MusicCatalogue.Logic/Factory/MusicCatalogueFactory.cs index df8fc11..a882219 100644 --- a/src/MusicCatalogue.Logic/Factory/MusicCatalogueFactory.cs +++ b/src/MusicCatalogue.Logic/Factory/MusicCatalogueFactory.cs @@ -25,6 +25,7 @@ public class MusicCatalogueFactory : IMusicCatalogueFactory private readonly Lazy> _genreStatistics; private readonly Lazy> _artistStatistics; private readonly Lazy> _monthlySpend; + private readonly Lazy> _retailerStatistics; public DbContext Context { get; private set; } public IGenreManager Genres { get { return _genres.Value; } } @@ -48,6 +49,9 @@ public class MusicCatalogueFactory : IMusicCatalogueFactory [ExcludeFromCodeCoverage] public IWishListBasedReport MonthlySpend { get { return _monthlySpend.Value; } } + [ExcludeFromCodeCoverage] + public IWishListBasedReport RetailerStatistics { get { return _retailerStatistics.Value; } } + public MusicCatalogueFactory(MusicCatalogueDbContext context) { Context = context; @@ -65,6 +69,7 @@ public MusicCatalogueFactory(MusicCatalogueDbContext context) _genreStatistics = new Lazy>(() => new WishListBasedReport(context)); _artistStatistics = new Lazy>(() => new WishListBasedReport(context)); _monthlySpend = new Lazy>(() => new WishListBasedReport(context)); + _retailerStatistics = new Lazy>(() => new WishListBasedReport(context)); } } } \ No newline at end of file diff --git a/src/MusicCatalogue.Logic/MusicCatalogue.Logic.csproj b/src/MusicCatalogue.Logic/MusicCatalogue.Logic.csproj index c0939a0..02e0d13 100644 --- a/src/MusicCatalogue.Logic/MusicCatalogue.Logic.csproj +++ b/src/MusicCatalogue.Logic/MusicCatalogue.Logic.csproj @@ -5,7 +5,7 @@ enable enable MusicCatalogue.Logic - 1.20.0.0 + 1.21.0.0 Dave Walker Copyright (c) Dave Walker 2023 Dave Walker @@ -17,19 +17,21 @@ https://github.com/davewalker5/MusicCatalogue MIT false - 1.20.0.0 + 1.21.0.0 + + diff --git a/src/MusicCatalogue.Logic/Sql/RetailerStatistics.sql b/src/MusicCatalogue.Logic/Sql/RetailerStatistics.sql new file mode 100644 index 0000000..046c036 --- /dev/null +++ b/src/MusicCatalogue.Logic/Sql/RetailerStatistics.sql @@ -0,0 +1,23 @@ +WITH RETAILER_SPEND ( Id, Name, IsWishListItem, Spend ) AS +( + SELECT r.Id, + r.Name, + IFNULL( al.IsWishListItem, 0), + SUM( IFNULL( al.Price, 0 ) ) + FROM ALBUMS al + LEFT OUTER JOIN RETAILERS r ON r.Id = al.RetailerId + GROUP BY r.Id, r.Name, IFNULL( al.IsWishListItem, 0) +) +SELECT RANK() OVER ( ORDER BY rsp.Name ASC ) AS "Id", + rsp.Name, + COUNT( DISTINCT a.Id ) AS "Artists", + COUNT( DISTINCT al.Id ) AS "Albums", + COUNT( DISTINCT t.Id ) AS "Tracks", + rsp.Spend +FROM RETAILER_SPEND rsp +INNER JOIN ALBUMS al ON al.RetailerId = rsp.Id +INNER JOIN TRACKS t ON t.AlbumId = al.Id +INNER JOIN ARTISTS a ON a.Id = al.ArtistId +WHERE rsp.IsWishListItem = $wishlist +AND IFNULL( al.IsWishListItem, 0 ) = $wishlist +GROUP BY rsp.Name diff --git a/src/MusicCatalogue.LookupTool/MusicCatalogue.LookupTool.csproj b/src/MusicCatalogue.LookupTool/MusicCatalogue.LookupTool.csproj index f863bfc..228da99 100644 --- a/src/MusicCatalogue.LookupTool/MusicCatalogue.LookupTool.csproj +++ b/src/MusicCatalogue.LookupTool/MusicCatalogue.LookupTool.csproj @@ -3,9 +3,9 @@ Exe net7.0 - 1.20.0.0 - 1.20.0.0 - 1.20.0 + 1.21.0.0 + 1.21.0.0 + 1.21.0 enable enable false