132 lines
5.6 KiB
Transact-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
|