0

我的 SQL Server 上有一个存储过程,它整合了一系列字段,用于报表生成器的 SSRS。该过程被提供一个 FileId,然后运行它的逻辑。在文件无法找到或引用 Solicitor 和 Arresting Officer 字段之前,它会按预期工作。

即使 fileId 没有关联的逮捕官或律师,我也需要它来返回结果。我敢肯定它很简单。基本上,如果 CTE 从查询中没有返回任何内容,我仍然需要一个默认行。

 ALTER PROCEDURE [dbo].[GetRollCallData] 
    @Ids        VARCHAR(255),
    @LexiconId  INT,
    @UUID       UNIQUEIDENTIFIER,
    @ReadOnly   INT
 AS


 DECLARE @TableCode INT
 SET @TableCode = 58

 IF @Ids <> ''
    BEGIN
        EXEC InsertInSelectionCache @Ids, @UUID, @TableCode, 0
        IF @ReadOnly = 1
            WITH DOACTE AS(
            SELECT ROW_NUMBER() OVER(PARTITION BY [File].Id ORDER BY CustomRecordsetId DESC) AS RowNumber, [File].*, FileType2Lexicon.Label as FileTypeLabel, [People].DefaultPhone, [People].InvertedName, CustomField.Name as FieldLabel, CustomFieldValue.Value as FieldValue
                FROM FileType2Lexicon, SelectionCache, [People], [File]
                INNER JOIN [CustomRecordSet]
                ON [CustomRecordset].RecordId = [File].Id
                INNER JOIN CustomFieldValue
                ON  [CustomRecordset].Id = CustomFieldValue.CustomRecordsetId
                INNER JOIN [CustomField2Lexicon]
                ON CustomField2Lexicon.CustomFieldId = CustomFieldValue.CustomFieldId
                INNER JOIN [CustomField]
                ON CustomField.Id = CustomField2Lexicon.CustomFieldId
                WHERE   [File].Id = SelectionCache.RecordId
                AND SelectionCache.UUID = @UUID
                AND SelectionCache.TableCode = @TableCode -- this is the code for File table  
                AND     [File].Id <> 0 
                AND     [File].FileTypeId = FileType2Lexicon.FileTypeId 
                AND     FileType2Lexicon.LexiconId = @LexiconId
                AND     [File].ClientIdString = [People].ClientIdString
                AND     CustomFieldValue.Value <> ''),

            SolicitorCTE AS(

                SELECT [People].Name AS SolicitorName, [File].Id
                FROM SelectionCache, [File]
                INNER JOIN [People2File]
                ON [People2File].FileId = [File].Id
                INNER JOIN [Role2Lexicon]
                ON [Role2Lexicon].RoleId = [People2File].RoleId
                INNER JOIN [People]
                ON [People].Id = [People2File].PeopleId
                WHERE 
                [File].Id = SelectionCache.RecordId
                AND SelectionCache.UUID = @UUID
                AND SelectionCache.TableCode = @TableCode -- this is the code for File table  
                AND [File].Id <> 0
                AND [Role2Lexicon].Label = 'Solicitor'),

             ArrestingOfficerCTE AS(
                SELECT ROW_NUMBER() OVER(PARTITION BY [File].Id ORDER BY [People].InvertedName ASC) AS RowNumber, [People].Name AS ArrestingOfficerName, [People].CompanyName AS ArrestingOfficerCompany, [File].Id
                FROM SelectionCache, [File]
                INNER JOIN [People2File]
                ON [People2File].FileId = [File].Id
                INNER JOIN [Role2Lexicon]
                ON [Role2Lexicon].RoleId = [People2File].RoleId
                INNER JOIN [People]
                ON [People].Id = [People2File].PeopleId
                WHERE 
                [File].Id = SelectionCache.RecordId
                AND SelectionCache.UUID = @UUID
                AND SelectionCache.TableCode = @TableCode -- this is the code for File table  
                AND [File].Id <> 0
                AND [Role2Lexicon].Label = 'Arresting Officer'),

            PivotCTE AS(
                SELECT *
                FROM
                (Select Id, FieldLabel, FieldValue FROM DOACTE) AS Source
                PIVOT(
                MAX(FieldValue) FOR FieldLabel IN ([Date_Arrest], [Graphic_Client], [Ticket_1], [Ticket_2], [Ticket_3], [Ticket_4], [Ticket_5], [Charge_1], [Charge_2], [Charge_3], [Charge_4], [Charge_5])) as Pvt
                )

            SELECT DOACTE.*, COALESCE(ArrestingOfficerCTE.ArrestingOfficerCompany, 'NULL')AS ArrestingOfficerCompany, COALESCE(ArrestingOfficerCTE.ArrestingOfficerName, 'NULL') AS ArrestingOfficerName, SolicitorCTE.SolicitorName, PivotCTE.[Date_Arrest], dbo.GetImagebyId(PivotCTE.[Graphic_Client]) as Photo, PivotCTE.[Ticket_1], PivotCTE.[Ticket_2], PivotCTE.[Ticket_3], PivotCTE.[Ticket_4], PivotCTE.[Ticket_5], PivotCTE.[Charge_1], PivotCTE.[Charge_2], PivotCTE.[Charge_3], PivotCTE.[Charge_4], PivotCTE.[Charge_5]
            FROM DOACTE
            INNER JOIN 
            PivotCTE
            ON DOACTE.Id = PivotCTE.Id
            INNER JOIN
            SolicitorCTE
            ON DOACTE.Id = SolicitorCTE.Id
            INNER JOIN
            ArrestingOfficerCTE
            ON DOACTE.Id = ArrestingOfficerCTE.Id
            WHERE DOACTE.RowNumber = 1
            AND ArrestingOfficerCTE.RowNumber = 1

        ELSE

        DELETE SelectionCache 
            WHERE UUID = @UUID
            AND   TableCode = @TableCode
    END
4

3 回答 3

1

您可以离开加入以获得可选结果。我还需要为逮捕官员添加一个空检查到 where caluse,这样尽管有左连接,它也不会排除记录。

SELECT DOACTE.*, COALESCE(ArrestingOfficerCTE.ArrestingOfficerCompany, 'NULL')AS ArrestingOfficerCompany, COALESCE(ArrestingOfficerCTE.ArrestingOfficerName, 'NULL') AS ArrestingOfficerName, SolicitorCTE.SolicitorName, PivotCTE.[Date_Arrest], dbo.GetImagebyId(PivotCTE.[Graphic_Client]) as Photo, PivotCTE.[Ticket_1], PivotCTE.[Ticket_2], PivotCTE.[Ticket_3], PivotCTE.[Ticket_4], PivotCTE.[Ticket_5], PivotCTE.[Charge_1], PivotCTE.[Charge_2], PivotCTE.[Charge_3], PivotCTE.[Charge_4], PivotCTE.[Charge_5]
            FROM DOACTE
            INNER JOIN 
            PivotCTE
            ON DOACTE.Id = PivotCTE.Id
            LEFT JOIN
            SolicitorCTE
            ON DOACTE.Id = SolicitorCTE.Id
            LEFT JOIN
            ArrestingOfficerCTE
            ON DOACTE.Id = ArrestingOfficerCTE.Id
            WHERE DOACTE.RowNumber = 1
            AND ( ArrestingOfficerCTE.RowNumber = 1 or ArrestingOfficerCTE.RowNumber is null )
于 2013-06-18T20:52:36.667 回答
0

你能试一下吗:

SELECT DOACTE.*, COALESCE(ArrestingOfficerCTE.ArrestingOfficerCompany, 'NULL')AS ArrestingOfficerCompany, COALESCE(ArrestingOfficerCTE.ArrestingOfficerName, 'NULL') AS ArrestingOfficerName, SolicitorCTE.SolicitorName, PivotCTE.[Date_Arrest], dbo.GetImagebyId(PivotCTE.[Graphic_Client]) as Photo, PivotCTE.[Ticket_1], PivotCTE.[Ticket_2], PivotCTE.[Ticket_3], PivotCTE.[Ticket_4], PivotCTE.[Ticket_5], PivotCTE.[Charge_1], PivotCTE.[Charge_2], PivotCTE.[Charge_3], PivotCTE.[Charge_4], PivotCTE.[Charge_5]
into #Results
            FROM DOACTE
            INNER JOIN 
            PivotCTE
            ON DOACTE.Id = PivotCTE.Id
            INNER JOIN
            SolicitorCTE
            ON DOACTE.Id = SolicitorCTE.Id
            INNER JOIN
            ArrestingOfficerCTE
            ON DOACTE.Id = ArrestingOfficerCTE.Id
            WHERE DOACTE.RowNumber = 1
            AND ArrestingOfficerCTE.RowNumber = 1

if ((select cout(*) from #Results) = 0)
begin

insert into #Results
      select
           .......your default values......

end

select * from #Results

drop table #Results
于 2013-06-14T20:29:52.650 回答
0

这几乎是liebs19 的回答,所以我支持他,因为他先到那里。我认为答案归结为LEFT JOIN你在哪里INNER。由于我重写了您的查询,因此我实际上可以理解发生了什么,并且我做了一些您可能想要或可能不想要的更改,所以我将它留在这里以防它有用。

我的行数比你的多,部分原因是我的格式不同,部分原因是我使用临时表做一次你做的事情大约 4 次。关于 CTE 的事情是,当你像这样堆叠它们时,你可能会得到一些非常粗糙的性能。CTE 的行为基本上就像一个动态视图,并且它们的 SQL 几乎到处都在重复。我正在接受您的限制[File]并将其移动到临时表中。然后我将它转为另一个(因为这进一步限制了基于RowNumber存在的事物1。然后我只是将它与最后的 2 个 CTE 一起使用并进入您的最终结果。

最后,SELECT * ...是邪恶的。我只在四处寻找某些东西时使用它。将它放入这样的存储过程中会导致架构或 CTE 等发生变化时出现问题。当你制作一个 sproc 时,为每一列命名,它在未来对你的影响会小得多。

在这里,如果您觉得它没有用,请随意忽略它:

ALTER PROCEDURE [dbo].[GetRollCallData] 
    @Ids        VARCHAR(255),
    @LexiconId  INT,
    @UUID       UNIQUEIDENTIFIER,
    @ReadOnly   INT
AS
BEGIN
    DECLARE @TableCode INT = 58;

    IF @Ids <> ''
    BEGIN
        EXEC InsertInSelectionCache @Ids, @UUID, @TableCode, 0

        IF @ReadOnly = 1
        BEGIN
            SELECT
                -- Add any other fully qualified columns. * is evil for sprocs. Only good for poking around in your own queries.
                AllFiles.Id
            INTO #SelectionFile
            FROM 
                [File] AllFiles
                INNER JOIN SelectionCache Cache
                    ON Cache.RecordId = AllFiles.Id
                    AND Cache.UUID = @UUID
                    AND Cache.TableCode = @TableCode -- this is the code for File table 
            WHERE
                AllFiles.Id <> 0

            ;WITH DOACTE AS
            (
                SELECT 
                    ROW_NUMBER() OVER(PARTITION BY SelectionFile.Id ORDER BY CustomRecordsetId DESC) AS RowNumber
                    , SelectionFile.Id AS FileId
                    -- [Replace with any other columns that you selected from [File] at the top.]
                    , Lexicon.Label AS FileTypeLabel
                    , [People].DefaultPhone
                    , [People].InvertedName
                    , CustomField.Name AS FieldLabel
                    , CustomFieldValue.Value AS FieldValue
                FROM 
                    #SelectionFile SelectionFile
                    INNER JOIN FileType2Lexicon Lexicon
                        ON Lexicon.FileTypeId = SelectionFile.FileTypeId
                        AND Lexicon.LexiconId = @LexiconId
                    INNER JOIN [People]
                        ON [People].ClientIdString = SelectionFile.ClientIdString
                    INNER JOIN [CustomRecordSet]
                        ON [CustomRecordset].RecordId = SelectionFile.Id
                    INNER JOIN CustomFieldValue
                        ON [CustomRecordset].Id = CustomFieldValue.CustomRecordsetId
                        AND CustomFieldValue.Value <> ''
                    INNER JOIN [CustomField2Lexicon]
                        ON CustomField2Lexicon.CustomFieldId = CustomFieldValue.CustomFieldId
                    INNER JOIN [CustomField]
                        ON CustomField.Id = CustomField2Lexicon.CustomFieldId
            )
            SELECT 
                Pvt.FileId
                -- [Replace with any other columns that you selected from DOACTE you want to propagate to the end.]
                , Pvt.[Date_Arrest]
                , Pvt.[Graphic_Client]
                , Pvt.[Ticket_1]
                , Pvt.[Ticket_2]
                , Pvt.[Ticket_3]
                , Pvt.[Ticket_4]
                , Pvt.[Ticket_5]
                , Pvt.[Charge_1]
                , Pvt.[Charge_2]
                , Pvt.[Charge_3]
                , Pvt.[Charge_4]
                , Pvt.[Charge_5]
            INTO #PivotedFile
            FROM
            (
                SELECT 
                    FileId
                    -- [Replace with any other columns that you selected from DOACTE you want to propagate to the end.]
                    , FieldLabel
                    , FieldValue 
                    , FieldLabel AS PivotFieldLabel
                    , FieldValue AS PivotFieldValue
                FROM 
                    DOACTE
                WHERE 
                    RowNumber = 1
            ) AS Source
            PIVOT
            (
                MAX(PivotFieldValue) 
                FOR PivotFieldLabel 
                IN 
                (
                    [Date_Arrest]
                    , [Graphic_Client]
                    , [Ticket_1]
                    , [Ticket_2]
                    , [Ticket_3]
                    , [Ticket_4]
                    , [Ticket_5]
                    , [Charge_1]
                    , [Charge_2]
                    , [Charge_3]
                    , [Charge_4]
                    , [Charge_5]
                )
            ) as Pvt

            ;WITH SolicitorCTE AS
            (
                SELECT 
                    [People].Name AS SolicitorName
                    , SelectedFiles.FileId
                FROM 
                    #PivotedFile SelectedFiles
                    INNER JOIN [People2File]
                        ON [People2File].FileId = SelectedFiles.FileId
                    INNER JOIN [Role2Lexicon]
                        ON [Role2Lexicon].RoleId = [People2File].RoleId
                        AND [Role2Lexicon].Label = 'Solicitor'
                    INNER JOIN [People]
                        ON [People].Id = [People2File].PeopleId
            )
            , ArrestingOfficerCTE AS
            (
                SELECT 
                    ROW_NUMBER() OVER(PARTITION BY SelectionFile.Id ORDER BY [People].InvertedName ASC) AS RowNumber
                    , [People].Name AS ArrestingOfficerName
                    , [People].CompanyName AS ArrestingOfficerCompany
                    , SelectedFiles.FileId
                FROM 
                    #PivotedFile SelectedFiles
                    INNER JOIN [People2File]
                        ON [People2File].FileId = SelectedFiles.FileId
                    INNER JOIN [Role2Lexicon]
                        ON [Role2Lexicon].RoleId = [People2File].RoleId
                        AND [Role2Lexicon].Label = 'Arresting Officer'
                    INNER JOIN [People]
                        ON [People].Id = [People2File].PeopleId
            )
            SELECT 
                SelectedFiles.Id
                -- [Replace with any other columns that you selected from DOACTE you want to propagate to the end.]
                , COALESCE(ArrestingOfficerCTE.ArrestingOfficerCompany, 'NULL') AS ArrestingOfficerCompany
                , COALESCE(ArrestingOfficerCTE.ArrestingOfficerName, 'NULL') AS ArrestingOfficerName
                , SolicitorCTE.SolicitorName
                , SelectedFiles.[Date_Arrest]
                , dbo.GetImagebyId(SelectedFiles.[Graphic_Client]) as Photo
                , SelectedFiles.[Ticket_1]
                , SelectedFiles.[Ticket_2]
                , SelectedFiles.[Ticket_3]
                , SelectedFiles.[Ticket_4]
                , SelectedFiles.[Ticket_5]
                , SelectedFiles.[Charge_1]
                , SelectedFiles.[Charge_2]
                , SelectedFiles.[Charge_3]
                , SelectedFiles.[Charge_4]
                , SelectedFiles.[Charge_5]
            FROM #PivotedFile SelectedFiles
                LEFT JOIN SolicitorCTE
                    ON SelectedFiles.FileId = SolicitorCTE.FileId
                LEFT JOIN ArrestingOfficerCTE
                    ON SelectedFiles.FileId = ArrestingOfficerCTE.FileId
                    AND ArrestingOfficerCTE.RowNumber = 1

        DROP TABLE #SelectionFile
        DROP TABLE #PivotedFile
        END
    ELSE
        DELETE SelectionCache 
        WHERE 
            UUID = @UUID
            AND TableCode = @TableCode
    END
END

(如果您确实使用它,请阅读-- [Replace...]评论。

于 2013-06-18T22:21:38.227 回答