INNER JOIN и Row_Num () Функциональные проблемы - PullRequest
1 голос
/ 05 января 2010

У меня есть хранимая процедура, которая выполняет сортировку pnd Paging, как Сортировка пользовательских постраничных результатов Скотта Мичелла.

У меня есть две таблицы: Article и Category. Моя хранимая процедура прекрасно работает для Article таблицы, но я хочу добавить в запрос столбец из таблицы Category (я имею в виду Inner Join).

На самом деле я не могу сделать это так, как Скотт Мичелл, потому что есть некоторые столбцы, которые похожи в обеих таблицах (когда я все время люблю Скотта, я получаю «Неоднозначную ошибку столбца»).

Моя хранимая процедура без внутреннего соединения:

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

ALTER PROCEDURE [dbo].[sp_Articles_SelectByCategoryId]
    @CategoryId int,
    @startRowIndex int = -1,
    @maximumRows int = -1,
    @sortExpression nvarchar(50),
    @recordCount int = NULL OUTPUT
AS
    IF (@recordCount IS NOT NULL)
    BEGIN
        SET @recordCount = (SELECT COUNT(*) 
                            FROM [dbo].[Articles] 
                            WHERE [CategoryId] = @CategoryId)
        RETURN
    END

    IF LEN(@sortExpression) = 0
       SET @sortExpression = 'Id'

    DECLARE @sql nvarchar(4000)

    SET @sql = 'SELECT [Id], [AddedDate], [AddedBy], [CategoryId],
                       [Title], [Abstract], [Body]
                FROM
                    (SELECT 
                         [Id], [AddedDate], [AddedBy], [CategoryId],
                         [Title], [Abstract], [Body],
                         ROW_NUMBER() OVER(ORDER BY ' + @sortExpression + ') as RowNum
                     FROM [dbo].[Articles]
                     WHERE CategoryId = ' + CONVERT(nvarchar(10), @CategoryId) + ') as CategoryIdInfo
         WHERE ((RowNum between (' + CONVERT(nvarchar(10), @startRowIndex) + ') AND ' + CONVERT(nvarchar(10), @startRowIndex) + ' + ' + CONVERT(nvarchar(10), @maximumRows) + ' - 1) 
   OR ' + CONVERT(nvarchar(10), @startRowIndex) + ' = -1 OR ' + CONVERT(nvarchar(10), @maximumRows) + ' = -1)'

      -- Execute the SQL query
      EXEC sp_executesql @sql

Моя Category таблица:

CREATE TABLE [dbo].[Category]
(
   [Id] [int] IDENTITY(1,1) NOT NULL,
   [AddedDate] [datetime] NOT NULL,
   [AddedBy] [nvarchar](250) COLLATE Arabic_CI_AS NOT NULL,
   [Title] [nvarchar](50) COLLATE Arabic_CI_AS NOT NULL,
   [Importance] [int] NOT NULL,
   [Description] [nvarchar](300) COLLATE Arabic_CI_AS NULL,
   [ImageUrl] [nvarchar](50) COLLATE Arabic_CI_AS NULL,

   CONSTRAINT [PK_Category] 
      PRIMARY KEY CLUSTERED ([Id] ASC)
)

Мой Article стол:

CREATE TABLE [dbo].[Articles]
(
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [AddedDate] [datetime] NOT NULL,
    [AddedBy] [nvarchar](250) COLLATE Arabic_CI_AS NOT NULL,
    [CategoryId] [int] NOT NULL,
    [Title] [nvarchar](255) COLLATE Arabic_CI_AS NOT NULL,
    [Abstract] [nvarchar](4000) COLLATE Arabic_CI_AS NULL,
    [Body] [nvarchar](max) COLLATE Arabic_CI_AS NOT NULL,
    [ReleaseDate] [datetime] NULL,
    [ExpireDate] [datetime] NULL,
    [Approved] [bit] NOT NULL,
    [Listed] [bit] NOT NULL,
    [CommentEnabled] [bit] NOT NULL,
    [OnlyForMembers] [bit] NOT NULL,
    [ViewCount] [int] NOT NULL,
    [Votes] [int] NOT NULL,
    [TotalRating] [int] NOT NULL,
 CONSTRAINT [PK_Articles] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

Я не знаю, как добавить в запрос столбец «Заголовок» таблицы «Категория».

Если в моей таблице Category не было похожих полей, этот запрос, безусловно, работает:

DECLARE @sql nvarchar(4000)
SET @sql = 
'SELECT
    [Id],
    [AddedDate],
    [AddedBy],
    [CategoryId],
    [Title],
    [Abstract],
    [Body],
    ArticleTitle
FROM
    (SELECT 

    [Id],
    [AddedDate],
    [AddedBy],
    a.[CategoryId],
    [Title],
    [Abstract],
    [Body],
    b.Title as CategoryTitle ,
ROW_NUMBER() OVER(ORDER BY ' + @sortExpression + ') as RowNum

    FROM  [dbo].[Articles] a INNER JOIN Category b on a.CategoryId = b.Id

    WHERE a.CategoryId = ' + CONVERT(nvarchar(10), @CategoryId) + '
    ) as CategoryIdInfo

Если вы хотите выполнить тестирование, вы можете загрузить приложение (таблицы и StoredProcedure) Спасибо

Ответы [ 2 ]

2 голосов
/ 05 января 2010

Следующий код отлично работает с вашими предоставленными таблицами - без данных в них, но это не должно иметь значения, так как я просто хочу доказать выполнение запроса, а не результаты.

Что следует отметить с этим кодом:

Выражение сортировки должно содержать псевдоним

SET @sortExpression = 'a.Id'       

Все дублированные столбцы должны иметь псевдонимы

Обратите внимание, что a. [Id], a. [AddedDate], a. [AddedBy], a. [CategoryId], a. [Title], b. [Title] все псевдонимы

Имена столбцов должны совпадать между внутренним и внешним запросами

У вас было имя столбца ArticleTitle в вашем внешнем выборе, но столбец CategoryTitle в вашем внутреннем выборе. Это никогда не сработает.

DECLARE @SortExpression nvarchar(100)
SET @sortExpression = 'a.Id'        

DECLARE @sql nvarchar(4000) 
SET @sql =  
'SELECT 
    [Id], 
    [AddedDate], 
    [AddedBy], 
    [CategoryId], 
    [Title], 
    [Abstract], 
    [Body], 
    CategoryTitle 
FROM 
    (SELECT  

    a.[Id], 
    a.[AddedDate], 
    a.[AddedBy], 
    a.[CategoryId], 
    a.[Title], 
    [Abstract], 
    [Body], 
    b.Title as CategoryTitle , 
ROW_NUMBER() OVER(ORDER BY ' + @sortExpression + ') as RowNum 

    FROM  [dbo].[Articles] a INNER JOIN Category b on a.CategoryId = b.Id 

    WHERE a.CategoryId = ' + CONVERT(nvarchar(10), @CategoryId) + ' 
    ) as CategoryIdInfo' 

      -- Execute the SQL query 
  EXEC sp_executesql @sql  
0 голосов
/ 05 января 2010

Вы пробовали что-то похожее на код ниже?

При этом используется ключевое слово AS для присвоения уникальных имен столбцам в вашем подзапросе, а также псевдонимы, позволяющие однозначно ссылаться на столбцы внутри подзапроса.

Также обратите внимание, что ALL ссылки на столбцы, которые являются неоднозначными, должны быть псевдонимами, в вашем случае это @sortExpression, который вы динамически вводите.

ALTER PROCEDURE [dbo].[sp_Articles_SelectByCategoryId]   
 @CategoryId int,   
 @startRowIndex int = -1,   
 @maximumRows int = -1,   
 @sortExpression nvarchar(50),   
 @recordCount int = NULL OUTPUT   

AS   

IF (@recordCount IS NOT NULL)   
 BEGIN   
  SET @recordCount = (SELECT COUNT(*) FROM [dbo].[Articles] WHERE [CategoryId] = @CategoryId   
 )   
  RETURN   
 END   

IF LEN(@sortExpression) = 0   
   SET @sortExpression = 'Id'

DECLARE @sql nvarchar(4000) 
SET @sql =  
'SELECT 
 [Id], 
 [AddedDate], 
 [AddedBy], 
 [CategoryId], 
 [Title], 
 -- CategoryTitle refers to the column name declared by that AS inside the subquery
 CategoryTitle
 [Abstract], 
 [Body], 

FROM 
 (SELECT  

 [Id], 
 [AddedDate], 
 [AddedBy], 
 -- The column aliases a and c allow us to refer to similarly names column unambiguously
 a.[CategoryId], 
 a.[Title], 
 c.[Title] as CategoryTitle,
 [Abstract], 
 [Body], 

--- This now includes an alias on the sortExpression order by
ROW_NUMBER() OVER(ORDER BY a.' + @sortExpression + ') as RowNum 

 FROM  [dbo].[Articles] a
 Join [dbo].[Category] c
 ON c.CategoryID = a.CategoryID
 WHERE c.CategoryId = ' + CONVERT(nvarchar(10), @CategoryId) + '

 ) as CategoryIdInfo 
 WHERE  
 ((RowNum between (' + CONVERT(nvarchar(10), @startRowIndex) + ') AND ' + CONVERT(nvarchar(10), @startRowIndex) + ' + ' + CONVERT(nvarchar(10), @maximumRows) + ' - 1)  
   OR ' + CONVERT(nvarchar(10), @startRowIndex) + ' = -1 OR ' + CONVERT(nvarchar(10), @maximumRows) + ' = -1)' 

  -- Execute the SQL query 
  EXEC sp_executesql @sql 

Для этого нужно объявить псевдоним как для Статей, так и для таблицы Категорий (a и c соответственно), что позволяет однозначно ссылаться на их столбцы.

Я не пробовал это с точным случаем использования Row_Number, но не могу придумать ни одной причины, по которой он не будет работать.

Тогда ключевое слово AS должно дать вам уникальное имя для использования с внешним выбором.

...