Внутреннее соединение дает нежелательный результат с номером строки на сервере sql

Я попытался выполнить разбиение данных на страницы при использовании ROW_NUMBER()
Вот мой запрос:

SELECT * FROM
    (SELECT ROW_NUMBER() OVER (ORDER BY OrderID) AS Row,* FROM SpecificOrders) 
    AS EMP
        inner join Users as c on EMP.UserID = c.UserID
        inner join Users as u on EMP.CreatedBy = u.UserID       
        inner join SpecificOrderPayment as p on EMP.OrderID= p.OrderID

    WHERE Row BETWEEN 0 AND 10 

Когда я выполняю этот запрос, я получаю следующий результат:

Row | OrderID | UserID |
1   |         |        |
5   |         |        |
6   |         |        |
7   |         |        |
8   |         |        |
9   |         |        |
10  |         |        |

Если я удалю это WHERE Row BETWEEN 0 AND 10 условие, мне будут предоставлены все записи

Здесь мой вопрос: почему я получаю только 7 строк и почему здесь 2,3 и 4 отсутствуют в столбце строки.

Более того, если я удалю третий запрос на соединение (SpecificOrderPayment), он даст мне правильный результат.


person Divyang Desai    schedule 14.09.2016    source источник
comment
Похоже, что в SpecificOrderPayment нет совпадающих записей для упомянутых вами случаев. Попробуйте использовать LEFT вместо INNER join.   -  person Giorgos Betsos    schedule 14.09.2016
comment
Как использовать функцию номера строки ?? посетите эту ссылку stackoverflow.com/questions/961007 / how-do-i-use-row-number   -  person Mukesh Kalgude    schedule 14.09.2016
comment
@GiorgosBetsos, да, понял.   -  person Divyang Desai    schedule 14.09.2016
comment
@MukeshKalgude Как использовать функцию числа строк? Нет, вопрос в другом.   -  person Divyang Desai    schedule 14.09.2016
comment
Потому что ваша строка 2 не соответствует условию внутреннего соединения, поэтому строка обрезана   -  person Joe Taras    schedule 14.09.2016
comment
@Div, ваш вопрос другой, но ваша концепция неверна, поэтому обратитесь по этой ссылке   -  person Mukesh Kalgude    schedule 14.09.2016
comment
Почему вы просто не используете SELECT TOP 10 * FROM SpecificOrders ... ПРИСОЕДИНЯЙТЕСЬ ....   -  person PyQL    schedule 14.09.2016
comment
@MukeshKalgude, ваша концепция неверна Как? Кстати, спасибо за ссылку   -  person Divyang Desai    schedule 14.09.2016
comment
@PyQL Почему я использую это? здесь, в вопросе, он статический, но он будет динамически использоваться из кода для целей нумерации страниц.   -  person Divyang Desai    schedule 14.09.2016
comment
Также я должен указать здесь, что если вы используете SQL Server 2012 и выше, вы можете использовать OFFSET / FETCH для реализации разбивки на страницы.   -  person S.Karras    schedule 14.09.2016
comment
Внутренние соединения отфильтровывают результат. Выполните только подзапрос и посмотрите результат. Затем посмотрите, как он себя ведет с соединениями. Также см. Ответ от @MtwStark.   -  person The Shooter    schedule 14.09.2016


Ответы (2)


у вас есть OrderID, которые являются пустыми или пустыми в SpecificOrders, и они сортируются вверх - в противном случае подход не является неправильным, хотя есть другие способы сделать это, например TOP 10 ... и т. д.

SELECT * FROM
(SELECT ROW_NUMBER() OVER (ORDER BY OrderID) AS Row,* FROM SpecificOrders 
                                                  WHERE RTRIM(COALESCE(OrderID, '')) <> '') 
AS EMP
    inner join Users as c on EMP.UserID = c.UserID
    inner join Users as u on EMP.CreatedBy = u.UserID       
    inner join SpecificOrderPayment as p on EMP.OrderID= p.OrderID

WHERE Row BETWEEN 0 AND 10 
person Cato    schedule 14.09.2016
comment
Это сработало, но что, если у меня есть одна другая таблица с именем SpecificOrderDetails, которая содержит несколько записей с одним идентификатором заказа, как это можно использовать? - person Divyang Desai; 14.09.2016
comment
@div, вы можете присоединиться с помощью OUTER APPLY и присоединиться только к ТОП-1 - я не уверен, чего вы хотите достичь, но какую информацию вы хотите получить от SpecificOrderDetails? - person Cato; 14.09.2016
comment
Я не знаю структуру таблиц, но я думал, что OrderId был чем-то вроде ключа, не допускающего значения NULL (первичного?) В таблице SpecificOrders, в этом случае проблема не там, а в другой объединенной таблице, наиболее вероятно, это SpecificOrderPayment потому что (я думаю) оплата не может быть обязательной для заказа, в то время как пользователь должен быть. последнее внутреннее соединение может быть опасным .. - person MtwStark; 30.09.2016
comment
@div, не могли бы вы запустить этот запрос? select count(*) from SpecificOrders where OrderID is null и опубликовать результат? - person MtwStark; 30.09.2016
comment
@div без проблем, мне просто интересно решение Андрея. Он считает, что проблема в том, что SpecificOrders.OrderID может иметь значение NULL, поэтому он предлагает отфильтровать его, прежде чем ВНУТРЕННИЕ присоединиться к другим таблицам. Я думаю, что проблема заключается в отсутствии связанной записи SpecificOrderPayment или (что менее вероятно) нулевых значений в столбцах SpecificOrders.UserID и SpecificOrders.CreatedBy, но в каждом случае внутренние объединения будут отфильтровывать из результата все заказы без оплаты или с нулевым идентификатором пользователя и создан таким образом, обязательно проверьте его. - person MtwStark; 30.09.2016
comment
@div Я не думаю, что левое соединение может давать повторяющиеся результаты, а внутреннее соединение - нет. если условие соединения совпадает с левым / внутренним, дает тот же результат, если не совпадает, левый сохраняет левую запись, а внутренний отбрасывает ее, но дубликаты не создаются, но я рад, что вы нашли подходящее для вас решение .... - person MtwStark; 30.09.2016

Проблема в том, что вы нумеруете строки SpecificOrders, а не конечный результат.

В вашем случае у вас есть только одна строка на заказ, поэтому использование левых соединений должно решить проблему.

Но если внутренний запрос может возвращать несколько строк для каждого OrderID, вы увидите один и тот же номер строки много раз.

И если соединение (внутреннее) отфильтрует некоторую строку, вы не получите этот номер строки в результате.

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

Попробуй это:

SELECT * 
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY EMP.OrderID) AS Row, EMP.*
    FROM SpecificOrders AS EMP
    left join Users as c on EMP.UserID = c.UserID
    left join Users as u on EMP.CreatedBy = u.UserID       
    left join SpecificOrderPayment as p on EMP.OrderID= p.OrderID
) D
WHERE [Row] BETWEEN 0 AND 10 
person MtwStark    schedule 14.09.2016
comment
ошибка связана с тем, что с SELECT * FROM вы получаете одно и то же имя столбца много раз, я исправлю SELECT, чтобы избежать проблемы - person MtwStark; 14.09.2016
comment
рада быть любой помощью. после EMP.* добавьте нужные столбцы из таблиц, а затем, если вам нравится это решение, примите его как лучший ответ - person MtwStark; 14.09.2016