La subconsulta SQL devuelve más de 1 valor

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);
                }

preguntado el 29 de junio de 12 a las 20:06

¿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:

¿Cuál es la problema? ¿Qué estás recibiendo y qué quieres obtener? Todo esto parece correcto hasta ahora. -

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:

El 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. -

@Amrit- Please include everything from the originating SQL call to the definition of all views, SProcs and functions... Desafortunadamente yes 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. -

3 Respuestas

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 dealIdy 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

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

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 or haz tu propia pregunta.