La subconsulta SQL devuelve más de 1 valor
Frecuentes
Visto 629 equipos
-1
Hola, estoy tratando de ejecutar una consulta para obtener una fila entre cierto número, como si estuviera tratando de obtener filas entre 10 y 20. entonces estoy usando una subconsulta para poder usar row_number()
función
La consulta falla con el error:
La subconsulta SQL devuelve más de 1 valor
Así que necesito encontrar una salida porque necesito obtener más de 1 resultado de la consulta.
PROCEDURE dbo.Search
(
@search_text varchar(max),
@search_category varchar(max),
@page int,
@COUNT INT OUTPUT
)
AS
SET NOCOUNT ON
DECLARE @Lower_limit int = (@page-1)*10;
DECLARE @Upper_limit int = (@page * 10) + 1;
-- SET @COUNT =0
IF @search_category='deal'
BEGIN
SET @COUNT = (SELECT COUNT(*) FROM dealData WHERE dealInfo LIKE '%' + @search_text + '%' OR dealName LIKE '%' + @search_text + '%' OR dealDescription LIKE '%' + @search_text + '%' GROUP BY dealId);
SELECT x.dealId , x.ROW
FROM
( SELECT dealId,ROW_NUMBER() OVER(ORDER BY dealId) as ROW from dealData WHERE dealInfo LIKE '%' + @search_text + '%' OR dealName LIKE '%' + @search_text + '%' OR dealDescription LIKE '%' + @search_text + '%' GROUP BY dealId)x
WHERE x.ROW < @Upper_limit AND x.ROW > @Lower_limit
END
Este es el procedimiento completo y cuando trato de llamarlo desde el siguiente código obtengo una excepción en _command.ExecuteReader(); Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
_query = "Search";
_command = new SqlCommand(_query, _connection);
_command.CommandType = CommandType.StoredProcedure;
_command.Parameters.AddWithValue("@search_text", search_text);
_command.Parameters.AddWithValue("@search_category", search_category);
_command.Parameters.AddWithValue("@page", page);
var returnParameter = _command.Parameters.Add("@COUNT", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.Output;
_reader = _command.ExecuteReader();
while (_reader.Read())
{
search_result index = new search_result();
index.category_id = this._categoryIdFromName(search_category);
index.post_id = _reader.GetValue(0).ToString();
_searchList.Add(index);
}
3 Respuestas
4
El problema es esta parte de tu sp:
SET @COUNT = ( SELECT COUNT(*) FROM dealData
WHERE dealInfo LIKE '%' + @search_text + '%'
OR dealName LIKE '%' + @search_text + '%'
OR dealDescription LIKE '%' + @search_text + '%'
GROUP BY dealId)
Específicamente, el GROUP BY dealId
parte. Si tienes varios dealId
en esa tabla, obtendrá varias filas como resultado. Obviamente, no puedes asignar eso en una variable escalar. O @Count
deberá declararse como una variable de tabla (lo que cambiará la lógica del resto de su sp), o se deshará del GROUP BY dealId
y verifique que le proporcione los resultados deseados.
Respondido el 29 de junio de 12 a las 21:06
La identificación del grupo es la clave principal, por lo tanto, ¿no se supone que debe ser único en el resultado? Amrit
@Amrit: parece que no entiendes el problema. Si dealId
es la clave principal, entonces es más fácil de explicar. Si las condiciones que pones en tu WHERE
devuelve más de una fila como resultado (supongamos que devuelve 3 filas), entonces, dado que está agrupando por clave principal, tendrá 3 filas con un valor de conteo de 1, en lugar de 1 fila con el valor de conteo de 3. Y, por supuesto, el resultado que está obteniendo no se puede asignar a una variable escalar. - Lamak
Agrupar por devolvería... DealID = 1, Count = 3 | ID de trato = 2, recuento = 2 | DealID = 3, Recuento = 5 ... etc. - Charleh
@Charleh: no realmente, sería: DealID = 1, Count = 1 | ID de trato = 2, recuento = 1 | ID de trato = 3, Recuento = 1 - Lamak
@Amrit tiene poco que ver con el hecho de que GroupID es la clave principal. Piensa en términos de lápices de colores. Su procedimiento almacenado está esperando una cuenta de lápices totales. Le está dando la cantidad de lápices azules, amarillos, verdes, rojos, etc. (que en cualquier cuadro dado será 1 de cada uno, como demuestra el comentario de Lamak). - fanfarrón
2
Tengo que estar de acuerdo con @Lamak, y solo estoy publicando una respuesta para que la repetición pueda infligir conocimiento. Si vuelve a escribir su tarea de la siguiente manera, su problema desaparecerá:
SELECT @COUNT = COUNT(*)
FROM dbo.dealData
WHERE dealInfo LIKE '%' + @search_text + '%'
OR dealName LIKE '%' + @search_text + '%'
OR dealDescription LIKE '%' + @search_text + '%'
/* GROUP BY dealId */ -- there is NO REASON for this grouping if you want total count!
;
Respondido el 29 de junio de 12 a las 21:06
0
Además de lo que todos los demás han dicho sobre la subconsulta que llena la variable que devuelve varias filas, puede haber un medio más eficiente para obtener lo que busca (que supongo que es la paginación). Esto supone que GroupId
es la clave primaria del DealData
tabla como se indica en los comentarios:
Declare @Results Table
(
DealId ... not null Primary Key
, RowNumAsc int not null
, TotalCount int not null
);
With NumberedData As
(
Select DealId
, Row_Number() Over ( Order By GroupId ) As RowNumAsc
, Row_Number() Over ( Order By GroupId Desc ) As RowNumDesc
From DealData
Where dealInfo LIKE '%' + @search_text + '%'
Or dealName LIKE '%' + @search_text + '%'
Or dealDescription LIKE '%' + @search_text + '%'
)
Insert @Results( DealId, RowNumAsc, TotalCount )
Select DealId, RowNumAsc
, Min( RowNumAsc + RowNumDesc - 1 ) As Count
From NumberedData
Where RowNumAsc < @UpperLimit
And RowNumAsc >= @LowerLimit
Group By DealId
Set @Count = ( Select TOP 1 TotalCount From @Results );
Select DealId, RowNumAsc
From @Results
Respondido el 29 de junio de 12 a las 22:06
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas .net sql sql-server subquery row-number or haz tu propia pregunta.
¿Estás seguro de que este es todo tu sql y que el sql anterior falla con el error que dijiste? De lo contrario, publique el SQL real que devuelve el mensaje de error: Jon Egerton
¿Cuál es la problema? ¿Qué estás recibiendo y qué quieres obtener? Todo esto parece correcto hasta ahora. - Sam DeHaan
Cuando trato de ejecutar este procedimiento obtengo esta excepción
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Pero cuando ejecuto el procedimiento con los mismos parámetros de sql management studio, obtengo el resultado esperado: AmritEl SQL que ha mostrado no puede generar ese error. ¿Lo estás llamando en un StoredProc? ¿Es parte de una función? Es
dealData
¿una vista? ¿Está incrustado en una consulta más grande? Incluya todo, desde la llamada SQL de origen hasta la definición de todas las vistas, Sprocs y funciones. - MatBailie@Amrit-
Please include everything from the originating SQL call to the definition of all views, SProcs and functions
... Desafortunadamenteyes
no es suficiente Necesitamos el código para todo el procedimiento almacenado, todas las vistas y funciones llamadas por eso, etc., etc. Parece bastante claro que cree que ha reducido el problema a una consulta, desafortunadamente el error es no en esa consulta directamente. - MatBailie