2009-09-25 4 views
7

nadzieję, że to jest trywialne dla SQL-Ninja ... stara się uzyskać następujące pracy zapytania:Korzystanie ranking-funkcja kolumna pochodzi w którym klauzula (SQL Server 2008)

To jest dla SQL Server 2008

SELECT 
    ROW_NUMBER() OVER (ORDER BY Date_Time DESC) AS RowNumber, * 
FROM 
    (SELECT 
     T.A_ID, T.User_Name, T.Date_Time, T.Value, 
     U.ID, U.Name, U.Field1, U.Field2, 
     COUNT(U.ID) OVER() AS TotalRows 
    FROM 
     TeeTable as T 
    INNER JOIN 
     YouTable AS U ON T.U_ID = U.ID 
    WHERE 
     T.Value BETWEEN 222 AND 225) Filtered 
WHERE 
    RowNumber BETWEEN 1 AND 5 

Wartości są nieco sprecyzowane, aby podać konkretny przykład, ale duch zapytania jest całkowicie zachowany. Błąd, który otrzymuję z tego oświadczenia, to:

Nieprawidłowa nazwa kolumny "Numer wiersza".

Jeśli usunąć końcowy WHERE (RowNumber MIĘDZY ...) zwraca oczekiwany zestaw wyników (A_ID, nazwa_użytkownika, DATE_TIME itp ...), z RowNumber jako kolumny (z wartościami sensical) we wspomnianym wyniki. Nie mogę jednak porównywać tego z klauzulą ​​WHERE. Wyraźnie robię coś głupiego, ale to przekracza mój limit SQL!

Próbowałem również zmienić to ustawienie jako CTE, (Z filtrem AS ...), ale efekt końcowy jest taki sam, wydaje się, że jest to po prostu cukier z tego, co i tak robię.

Pomysły? Jak mogę filtrować względem kolumny pochodnej RowNumber?

+0

Unikaj znacznika 'mssql', ponieważ łatwo go pomylić z' mysql' –

Odpowiedz

15

Musisz przenieść operatora WHERE powyżej listę projektów, gdzie kolumna RowNumber jest utworzona. Użyj tabeli uzyskane lub CTE:

SELECT * 
    FROM (
    SELECT *, ROW_NUMBER() OVER (...) as RowNumber 
    FROM ...) As ... 
WHERE RowNumber = ... 

odpowiednik CTE jest:

WITH cte AS (
SELECT *, ROW_NUMBER() OVER (...) as RowNumber 
     FROM ...) 
SELECT * FROM cte 
WHERE RowNumber = ... 
+0

Działa świetnie, dzięki! –

3

Funkcje okienne (z których ROW_NUMBER jest najlepsza wiedza) są wypełnione bardzo późno w zapytaniu, a po klauzula WHERE. Dlatego trzeba też to gniazdo, aby filtrować na nim:

SELECT * 
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY Date_Time DESC) AS RowNumber, * 
    FROM 
    (SELECT T.A_ID, T.User_Name, T.Date_Time, T.Value, 
      U.ID, U.Name, U.Field1, U.Field2, 
      COUNT(U.ID) OVER() AS TotalRows 
     FROM 
     TeeTable as T INNER JOIN YouTable AS U 
     ON T.U_ID = U.ID 
     WHERE T.Value BETWEEN 222 AND 225 
    ) Numbered 
) Filtered 
WHERE RowNumber BETWEEN 1 AND 5 

Można również umieścić je w CTE użytkownika lub widoków, aby uzyskać ten sam efekt.

+0

Nie mogę przyjąć 2 odpowiedzi, ale zrobię to. :) Dzięki! –

0

Problem z zapytaniem pojawia się z powodu błędu w logicznej kolejności przetwarzania. Jest to logiczna kolejność przetwarzania określona w sieci deweloperów MSDN.

Logiczne przetwarzanie Kolejność instrukcji SELECT Poniższe kroki przedstawiają logiczną kolejność przetwarzania lub kolejność wiązania dla instrukcji SELECT. Ta kolejność określa, kiedy obiekty zdefiniowane w jednym kroku są udostępniane klauzulom w kolejnych krokach. Na przykład, jeśli procesor kwerend może wiązać (uzyskiwać dostęp) tabele lub widoki zdefiniowane w klauzuli FROM, te obiekty i ich kolumny są udostępniane dla wszystkich kolejnych kroków. I odwrotnie, ponieważ klauzula SELECT jest krokiem 8, nie można odwoływać się do klauzul poprzedzających do jakichkolwiek aliasów kolumn lub kolumn pochodnych zdefiniowanych w tej klauzuli. Jednak mogą się do nich odwoływać kolejne klauzule, takie jak klauzula ORDER BY. Należy zauważyć, że faktyczne fizyczne wykonanie instrukcji jest określane przez procesor kwerend i kolejność może różnić się od tej listy. OD NA DOŁĄCZ GDZIE GROUP BY WITH CUBE lub ROLLUP BIORĄC SELECT DISTINCT ORDER BY TOP

więc wprowadzić funkcję rankingową jako alias w podzapytania w od sekcji, a potem będzie w stanie ustawić warunek dla aliasu w sekcji gdzie.

Powodzenia ... !!