PlotDirector/PlotLine/Sql/152_NameLibraryAllLocalesDefault.sql

132 lines
5.6 KiB
Transact-SQL

SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
CREATE OR ALTER PROCEDURE dbo.GivenName_Search
@UserID int,
@ProjectID int,
@BookID int = NULL,
@Search nvarchar(120) = NULL,
@LocaleCode nvarchar(16) = NULL,
@BirthYear int = NULL,
@GenderPreference nvarchar(12) = NULL,
@GenderThreshold decimal(9,4) = NULL,
@NameType nvarchar(40) = NULL,
@MinimumUsage decimal(9,4) = NULL,
@UsedScope nvarchar(20) = N'Project',
@UsedOnly bit = NULL,
@Page int = 1,
@PageSize int = 25
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM dbo.ProjectUserAccess WHERE ProjectID = @ProjectID AND UserID = @UserID AND IsActive = 1)
BEGIN
SELECT TOP (0) CAST(NULL AS int) AS GivenNameID;
RETURN;
END;
IF @Page < 1 SET @Page = 1;
IF @PageSize < 1 SET @PageSize = 25;
IF @PageSize > 100 SET @PageSize = 100;
DECLARE @NameLocaleID int = NULL;
IF @LocaleCode IS NOT NULL
BEGIN
SELECT TOP (1) @NameLocaleID = NameLocaleID FROM dbo.NameLocales WHERE LocaleCode = @LocaleCode AND IsActive = 1;
END;
;WITH UsageChoice AS
(
SELECT
u.*,
l.LocaleCode,
l.DisplayName AS LocaleDisplayName,
ROW_NUMBER() OVER (PARTITION BY u.GivenNameID ORDER BY
CASE WHEN @BirthYear IS NOT NULL AND @BirthYear BETWEEN u.BirthYearFrom AND u.BirthYearTo THEN 0 ELSE 1 END,
CASE WHEN @BirthYear IS NULL THEN ABS(1960 - ((u.BirthYearFrom + u.BirthYearTo) / 2)) ELSE ABS(@BirthYear - ((u.BirthYearFrom + u.BirthYearTo) / 2)) END,
u.UsageWeight DESC) AS rn
FROM dbo.NameUsages u
INNER JOIN dbo.NameLocales l ON l.NameLocaleID = u.NameLocaleID
WHERE u.IsActive = 1
AND (@NameLocaleID IS NULL OR u.NameLocaleID = @NameLocaleID)
),
Used AS
(
SELECT g.GivenNameID, COUNT(DISTINCT c.CharacterID) AS UsedCount,
STRING_AGG(CONVERT(nvarchar(max), c.CharacterName + N' (' + p.ProjectName + COALESCE(N' / ' + b.BookTitle, N'') + N')'), N'; ') AS UsedSummary
FROM dbo.GivenNames g
INNER JOIN
(
SELECT c.CharacterID, c.ProjectID, c.CharacterName, c.CharacterName AS MatchedName
FROM dbo.Characters c
WHERE c.IsArchived = 0
UNION ALL
SELECT c.CharacterID, c.ProjectID, c.CharacterName, ca.Alias AS MatchedName
FROM dbo.CharacterAliases ca
INNER JOIN dbo.Characters c ON c.CharacterID = ca.CharacterID
WHERE c.IsArchived = 0
) c ON UPPER(LTRIM(RTRIM(c.MatchedName))) = g.NormalisedName COLLATE Latin1_General_100_CI_AI_SC
INNER JOIN dbo.Projects p ON p.ProjectID = c.ProjectID
INNER JOIN dbo.ProjectUserAccess pua ON pua.ProjectID = c.ProjectID AND pua.UserID = @UserID AND pua.IsActive = 1
LEFT JOIN dbo.Books b ON b.ProjectID = c.ProjectID AND b.IsArchived = 0
WHERE (@UsedScope = N'Library' OR c.ProjectID = @ProjectID)
AND (@BookID IS NULL OR @UsedScope <> N'Book' OR b.BookID = @BookID)
GROUP BY g.GivenNameID
),
Related AS
(
SELECT x.GivenNameID,
STRING_AGG(CONVERT(nvarchar(max), x.DisplayName), N', ') AS RelatedForms
FROM
(
SELECT r.FromGivenNameID AS GivenNameID, t.DisplayName
FROM dbo.NameRelationships r
INNER JOIN dbo.GivenNames t ON t.GivenNameID = r.ToGivenNameID
WHERE r.IsActive = 1
UNION
SELECT r.ToGivenNameID AS GivenNameID, f.DisplayName
FROM dbo.NameRelationships r
INNER JOIN dbo.GivenNames f ON f.GivenNameID = r.FromGivenNameID
WHERE r.IsActive = 1 AND r.IsBidirectional = 1
) x
GROUP BY x.GivenNameID
),
Filtered AS
(
SELECT
g.GivenNameID, g.GivenNameKey, g.DisplayName, g.NormalisedName, g.NameType, g.IsWordAmbiguous,
u.MaleWeight, u.FemaleWeight, u.UsageWeight, u.Confidence, u.BirthYearFrom, u.BirthYearTo, u.LocaleCode, u.LocaleDisplayName, u.SourceType,
rel.RelatedForms,
COALESCE(used.UsedSummary, N'') AS UsedSummary,
COALESCE(used.UsedCount, 0) AS UsedCount,
COUNT(1) OVER() AS TotalRows
FROM dbo.GivenNames g
LEFT JOIN UsageChoice u ON u.GivenNameID = g.GivenNameID AND u.rn = 1
LEFT JOIN Used used ON used.GivenNameID = g.GivenNameID
LEFT JOIN Related rel ON rel.GivenNameID = g.GivenNameID
WHERE g.IsActive = 1
AND (@Search IS NULL OR g.NormalisedName LIKE UPPER(LTRIM(RTRIM(@Search))) + N'%' COLLATE Latin1_General_100_CI_AI_SC OR g.DisplayName LIKE @Search + N'%')
AND (@NameType IS NULL OR g.NameType = @NameType)
AND (@MinimumUsage IS NULL OR u.UsageWeight >= @MinimumUsage)
AND (@UsedOnly IS NULL OR (@UsedOnly = 1 AND COALESCE(used.UsedCount, 0) > 0) OR (@UsedOnly = 0 AND COALESCE(used.UsedCount, 0) = 0))
AND (
@GenderPreference IS NULL
OR @GenderThreshold IS NULL
OR (@GenderPreference = N'Female' AND u.FemaleWeight >= @GenderThreshold)
OR (@GenderPreference = N'Male' AND u.MaleWeight >= @GenderThreshold)
OR (@GenderPreference = N'Mixed' AND u.MaleWeight >= (1 - @GenderThreshold) AND u.FemaleWeight >= (1 - @GenderThreshold))
)
)
SELECT *
FROM Filtered
ORDER BY
CASE WHEN @Search IS NOT NULL AND NormalisedName = UPPER(LTRIM(RTRIM(@Search))) COLLATE Latin1_General_100_CI_AI_SC THEN 0 ELSE 1 END,
UsageWeight DESC,
DisplayName
OFFSET (@Page - 1) * @PageSize ROWS FETCH NEXT @PageSize ROWS ONLY;
END;
GO