Vector repeats the data of a query

1

my problem is that I have the following query:

        SELECT respuestaId, respuesta, estado, r.preguntaId FROM respuestas r, preguntas p WHERE r.preguntaId = p.preguntaId AND r.preguntaId = 1

The result of the query is 4 responses, for example "resp1", "resp2", "resp3", "resp4". I keep it in the vector in the following way:

        clsMtoRespuestas resp = new clsMtoRespuestas();
             resp.setPreguntaId(pregunta);

             if(resp.ConsultarRespuestasPorPregunta()) {
                  for(int i = 0; i <= 3;i++){
                  respuestas[i] = resp.getRespuesta();
                  }
             }

My idea is that each answer is saved in a space of the vector but when it comes to showing these answers in a few jButtons it shows that only the first answer ("resp1") has been saved in the 4 spaces of the vector.

(I also put the code of how I show them so that there is no doubt whether I am the one that repeats the indices)

        btnResp1.setText(respuestas[0]);
        btnResp2.setText(respuestas[3]);
        btnResp3.setText(respuestas[1]);
        btnResp4.setText(respuestas[2]);

I want to know if there is an error in the way of saving the answers in the vector or if there is another way to do it. In advance, thank you.

I call the data from a class like this:

        public boolean ConsultarRespuestasPorPregunta() {
             boolean resp = false;
             try{
                  String sql = "SELECT respuestaId, respuesta, estado, r.preguntaId FROM respuestas r, preguntas p WHERE r.preguntaId = p.preguntaId AND r.preguntaId = ?;";
                  PreparedStatement cmd = cn.prepareStatement(sql);
                  cmd.setInt(1, preguntaId);
                  ResultSet rs = cmd.executeQuery();
                  if(rs.next()){
                      resp = true;
                      respuestaId = rs.getInt(1);
                      respuesta = rs.getString(2);
                      estado = rs.getInt(3);
                      preguntaId = rs.getInt(4);
                  }
                  cmd.close();
                  //getCn().close();

             }
             catch (SQLException e){
                  System.out.println(e.toString());
             }
             return resp;
       }
    
asked by Andres Henriquez 07.09.2017 в 03:27
source

2 answers

1

For this kind of problems I usually use MySQL GROUP_CONCAT combined with GROUP BY .

I recommend using this form, especially if in the query all the other data will always be the same, except for the answers. Imagine the redundant data that you will have if the query retrieves 50 or 100 responses , we are talking about 50 or 100 rows with the same: Pregunta 1, Pregunta 1, Pregunta 1 , etc, where the only thing that will vary is the response.

So, better to group the data and concatenate the answers with a separator, right? That way you'll handle a single row of data.

Unfortunately, that function does not exist in SQL Server, but we can simulate something similar by doing this:

SELECT
     t1.[preguntaId],
     STUFF(
         (SELECT '|' + respuesta
          FROM respuestas_20170906 r
          INNER JOIN preguntas_20170906 p ON r.[preguntaId]=p.[preguntaId]
          WHERE r.[preguntaId]=1
          FOR XML PATH (''))
          , 1, 1, '')  AS respuestas 
FROM respuestas_20170906 AS t1 WHERE t1.[preguntaId]=1
GROUP BY [preguntaId];

You will have a respuestas column with data similar to these:

Respuesta1|Respuesta2|Respuesta3|Respuesta5

Doing a split through | will have an array with the answers. That way you will be driving a single row with all your data and you will not need loops to read them.

Código: SEE ON REXTESTER

CREATE TABLE  preguntas_20170906
    ([preguntaId] int, [pregunta] varchar(30))
;


CREATE TABLE  respuestas_20170906
    ([respuestaId] int, [respuesta] varchar(30), [preguntaId] int, [estado] int)
;



INSERT INTO preguntas_20170906
    ([preguntaId], [pregunta])
VALUES
    (1, 'Pregunta1'),
    (2, 'Pregunta2'),
    (3, 'Pregunta3'),
    (4, 'Pregunta4')
;


INSERT INTO respuestas_20170906
    ([respuestaId], [respuesta], [preguntaId])
VALUES
    (1, 'Respuesta1', 1),
    (2, 'Respuesta2', 1),
    (3, 'Respuesta3', 2),
    (4, 'Respuesta4', 1),
    (5, 'Respuesta5', 1)

;


-- SELECT * FROM respuestas_20170906;
-- SELECT * FROM preguntas_20170906;



SELECT
     t1.[preguntaId],
     STUFF(
         (SELECT '|' + respuesta
          FROM respuestas_20170906 r
          INNER JOIN preguntas_20170906 p ON r.[preguntaId]=p.[preguntaId]
--          WHERE r.[preguntaId] = t1.[preguntaId] AND r.[preguntaId]=1
          FOR XML PATH (''))
          , 1, 1, '')  AS respuestas 
FROM respuestas_20170906 AS t1 WHERE t1.[preguntaId]=1
GROUP BY [preguntaId];

Resultado:

preguntaId      respuestas
1               Respuesta1|Respuesta2|Respuesta3|Respuesta5

If you need to concatenate more than one column:

- Several concatenated values: since state is INT you have to make a CAST

SELECT
     t1.[preguntaId],
     STUFF(
         (SELECT '|' + respuesta + '_' + CAST(estado AS VARCHAR)
          FROM respuestas_20170906 r
          INNER JOIN preguntas_20170906 p ON r.[preguntaId]=p.[preguntaId]
          WHERE r.[preguntaId]=1
          FOR XML PATH (''))
          , 1, 1, '')  AS respuestas 
FROM respuestas_20170906 AS t1 WHERE t1.[preguntaId]=1
GROUP BY [preguntaId];

Resultado:

preguntaId     respuestas
1              Respuesta1_10|Respuesta2_50|Respuesta4_90|Respuesta5_33

Here you would have to split first on | and then on _ to get:

Respuesta1
 10
Respuesta2
 50
Respuesta4
 90
Respuesta5
 33
    
answered by 07.09.2017 / 04:23
source
1

Good morning

As I mention you remember (and use) almost nothing of Java the following I hope you of idea of my exposition and you "translate" it as in the reality it is of utility to you.

class clsMtoRespuestas {

   private int indiceActual; // aqui el elemento a obtener
   private int[] respuestaId; // iniciarlizarlo 
   private string[] respuesta; // iniciarlizarlo 
   private int[] estado; // iniciarlizarlo 
   private int[] preguntaId; // iniciarlizarlo 

    public boolean ConsultarRespuestasPorPregunta() {
         boolean resp = false;
          /* Inicializar los vecrores */
          indiceActual=0; /* creo recordar el primer elemento es en posición 0 (cero) */
         try{
              String sql = "SELECT respuestaId, respuesta, estado, r.preguntaId FROM respuestas r, preguntas p WHERE r.preguntaId = p.preguntaId AND r.preguntaId = ?;";
              PreparedStatement cmd = cn.prepareStatement(sql);
              cmd.setInt(1, preguntaId);
              ResultSet rs = cmd.executeQuery();
              /*if(rs.next()){*/ /* En vez del if usar while */
              while (rs.next())
                  resp = true;
                  /* Asumiendo cada vector inicializado con tantos elemento como devuelve la consulta
                     usamos temporalmente indiceActual para llenarlo */
                  respuestaId[indiceActual] = rs.getInt(1);
                  respuesta[indiceActual] = rs.getString(2);
                  estado[indiceActual] = rs.getInt(3);
                  preguntaId[indiceActual] = rs.getInt(4);
                  indiceActual++; /* Incrementar indice actual */
              }
              cmd.close();
              //getCn().close();
             /* terminamos de obtener todo y ponesmo indiceActual en 0 (cero) */
             indiceActual=0;
         }
         catch (SQLException e){
              System.out.println(e.toString());
         }
         return resp;
    } // ConsultarRespuestasPorPregunta

    public string getRespuesta() {
       /* Asumo est devuelve el vector "respuesta" */ 
       string devolver= respuesta[indiceActual]; /* tomamos el valor */
       return devolver;
    } // getRespuesta

    public boolean next() {
       indiceActual++; /* Incrementamos indiceActual */
       /* Pensado todos los vectores tienen la misma cantidad de elementos
          usamos cualquiera para comprobar si llegamos al final */
       return (respuesta.length<indiceActual);
    } // next
}

With the above for the part you have:

clsMtoRespuestas resp = new clsMtoRespuestas();
resp.setPreguntaId(pregunta);

if(resp.ConsultarRespuestasPorPregunta()) {
  int i =0;
  while(resp.next())
     respuestas[i++] = resp.getRespuesta();
  }
}

Hoping to have understood what you wish to do, I wish you guidance.

    
answered by 07.09.2017 в 04:27