Cuando trabajé en el Zend Framework's database component, intentamos abstraer la funcionalidad de la cláusula LIMIT
admitida por MySQL, PostgreSQL y SQLite. Es decir, la creación de una consulta se podría hacer de esta manera:Emular la cláusula LIMIT de MySQL en Microsoft SQL Server 2000
$select = $db->select();
$select->from('mytable');
$select->order('somecolumn');
$select->limit(10, 20);
Cuando la base de datos soporta LIMIT
, esto produce una consulta SQL como la siguiente:
SELECT * FROM mytable ORDER BY somecolumn LIMIT 10, 20
Esto fue más complejo para las marcas de base de datos que no es compatible con LIMIT
(esa cláusula no es parte del lenguaje SQL estándar, por cierto). Si puede generar números de fila, haga que toda la consulta sea una tabla derivada, y en la consulta externa use BETWEEN
. Esta fue la solución para Oracle e IBM DB2. Microsoft SQL Server 2005 tiene una función de número de fila similar, por lo que uno puede escribir la consulta de esta manera:
SELECT z2.*
FROM (
SELECT ROW_NUMBER OVER(ORDER BY id) AS zend_db_rownum, z1.*
FROM (...original SQL query...) z1
) z2
WHERE z2.zend_db_rownum BETWEEN @offset+1 AND @[email protected];
Sin embargo, Microsoft SQL Server 2000 no tienen la función ROW_NUMBER()
.
Así que mi pregunta es, ¿se te ocurre una manera de emular la funcionalidad LIMIT
en Microsoft SQL Server 2000, utilizando únicamente SQL? Sin usar cursores o T-SQL o un procedimiento almacenado. Tiene que admitir ambos argumentos para LIMIT
, tanto el recuento como el desplazamiento. Las soluciones que usan una tabla temporal tampoco son aceptables.
Editar:
La solución más común para MS SQL Server 2000 parece ser como la de abajo, por ejemplo, para obtener filas 50 a 75:
SELECT TOP 25 *
FROM (
SELECT TOP 75 *
FROM table
ORDER BY BY field ASC
) a
ORDER BY field DESC;
Sin embargo, este doesn' t funciona si el conjunto total de resultados es, digamos 60 filas. La consulta interna devuelve 60 filas porque está en el top 75. Luego, la consulta externa devuelve las filas 35-60, que no cabe en la "página" deseada de 50-75. Básicamente, esta solución funciona a menos que necesite la última "página" de un conjunto de resultados que no sea un múltiplo del tamaño de la página.
Editar:
Otra solución funciona mejor, pero sólo si puede asumir el conjunto de resultados incluye una columna que es único:
SELECT TOP n *
FROM tablename
WHERE key NOT IN (
SELECT TOP x key
FROM tablename
ORDER BY key
);
Conclusión:
Ningún general solución de propósito parece existir para emular LIMIT
en MS SQL Server 2000. Existe una buena solución si puede usar la función ROW_NUMBER()
ion en MS SQL Server 2005.
Sí, esto está cerca, pero sólo funciona cuando hay una clave única en el resultado de la consulta provisional. ¿Cómo lo haría en una consulta GROUP BY o para una consulta que une varias tablas? –