MySQL - Creo que mi consulta no esta bien del todo

 
Vista:

Creo que mi consulta no esta bien del todo

Publicado por Rocko3000 (4 intervenciones) el 08/06/2018 14:45:51
Hola amigos,
lo que pretendo hacer con mi consulta es lo siguiente:

quiero selecionar todos los videos que pertenecen a un canal y ademas que la id del video sea posterior a 20.

SELECT * FROM videos WHERE id_canal IN (id_canal) AND id < 20

hasta creo que esta bien, el problema lo tengo porque ademas de todo lo anterior quiero que no me muestre los videos con id 45,46 y 47. Yo lo hago de la siguiente forma:

SELECT * FROM videos WHERE id_canal IN (id_canal) AND id NOT IN (45,46,47) AND id < 20


pero no estoy muy convencido de que este bien.

alguna idea?

saludos
muchas gracias !!!
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil
Val: 953
Oro
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

Creo que mi consulta no esta bien del todo

Publicado por leonardo_josue (414 intervenciones) el 08/06/2018 16:28:31
Hola Rocko3000:

Algunos comentarios para tu consulta.

Primero dices esto:

1
quiero selecionar todos los videos que pertenecen a un canal

En ese caso, no es recomendable que utilices la cláusula IN, sino es mejor hacer una igualación... IN la utilizas cuando tienes que evaluar varios valores posibles de un campo, pero no es recomendable usarla ya que tiene un performance bastante malo... entonces yo haría algo así:

1
2
3
..
WHERE id_canal = mi_id_canal
...

en donde mi_id_canal es el valor o el parámetro que quieres buscar.

Segundo, dices esto:

1
ademas que la id del video sea posterior a 20

Sin embargo, en la condición utilizas el símbolo de MENOR QUE, por lo tanto, la consulta te traerá todos los ID's menores a 20.

Tercero, la ultima condición con NOT IN es correcta, ya que aquí si quieres evaluar varios valores

Finalmente, no es una buena práctica hacer un SELECT *, aun incluso cuando necesites TODOS LOS CAMPOS de tu tabla, cosa que por lo general nunca es así y necesitas sólo una parte, pero aun en el caso de que necesites todos los campos, es mejor LISTARLOS en lugar de poner asterisco (*).

Entonces, la consulta creo que sería mejor así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> SELECT * FROM tabla;
+------+----------+---------------------+--------------+
| id   | id_canal | campo1              | campo2       |
+------+----------+---------------------+--------------+
|   19 |        1 | video 19            | campo basura |
|   20 |        1 | video 20            | campo basura |
|   45 |        1 | video 45            | campo basura |
|   46 |        1 | video 46            | campo basura |
|   47 |        1 | video 47            | campo basura |
|   48 |        1 | video 48            | campo basura |
|   44 |        2 | video 44 otro canal | campo basura |
|   45 |        2 | video 45 otro canal | campo basura |
+------+----------+---------------------+--------------+
8 rows in set (0.00 sec)


1
2
3
4
5
6
7
8
9
10
11
mysql> SELECT id, campo1
    -> FROM tabla
    -> WHERE id_canal = 1
    ->   AND id NOT IN (45,46,47)
    ->   AND id > 20;
+------+----------+
| id   | campo1   |
+------+----------+
|   48 | video 48 |
+------+----------+
1 row in set (0.00 sec)

Haz la prueba y nos comentas.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Creo que mi consulta no esta bien del todo

Publicado por Rocko3000 (4 intervenciones) el 08/06/2018 16:46:41
Hola Leonardo,
utilice la cláusula IN para la id del canal porque el campo id_canal puede guardar varias ids en caso de que el video pueda pertenecer a mas de un canal.
Quedan guardadas asi: 2,18,56 (con las comas)

Probé la opcion que tu me deicas id_canal = 1, pero creo que solo sirve cuando tiene una id.


saludos
gracias :)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 953
Oro
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

Creo que mi consulta no esta bien del todo

Publicado por leonardo_josue (414 intervenciones) el 08/06/2018 18:35:52
Hola de nuevo Rocko3000


1
2
utilice la cláusula IN para la id del canal porque el campo id_canal puede guardar varias ids en caso de que el video pueda pertenecer a mas de un canal.
Quedan guardadas asi: 2,18,56 (con las comas)

Esto es un TERRIBLE ERROR DE DISEÑO... tan grave que si estuvieras en una clase de Modelado de Base de Datos, esto seguramente te haría repetir el curso y si fueras un DBA de una empresa, te podría costar el puesto O_o

Por ningún motivo un campo debe ser MULTIVALUADO... o en todo caso, lo que haces es modelar la relación con MAS DE UNA TABLA... es decir, en lugar de tener esto:

1
2
3
4
5
6
7
8
9
mysql> SELECT * FROM tabla;
+------+----------+----------+--------------+
| id   | id_canal | campo1   | campo2       |
+------+----------+----------+--------------+
| 19   | 1        | video 19 | campo basura |
| 20   | 1,2      | video 20 | campo basura |
| 45   | 1,2,3    | video 45 | campo basura |
+------+----------+----------+--------------+
3 rows in set (0.00 sec)

Lo que haces es un modelo de tres tablas, dos catálogos y una tabla de relación:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
mysql> SELECT * FROM videos;
+----------+----------+--------------+
| id_video | campo1   | campo2       |
+----------+----------+--------------+
| 19       | video 19 | campo basura |
| 20       | video 20 | campo basura |
| 45       | video 45 | campo basura |
+----------+----------+--------------+
3 rows in set (0.00 sec)
 
mysql> SELECT * FROM canales;
+----------+-------------+
| id_canal | descripcion |
+----------+-------------+
| 1        | canal uno   |
| 2        | canal dos   |
| 3        | canal tres  |
+----------+-------------+
3 rows in set (0.00 sec)
 
mysql> SELECT * FROM videos_canales;
+----------------+----------+----------+
| id_video_canal | id_video | id_canal |
+----------------+----------+----------+
|              1 | 19       | 1        |
|              2 | 20       | 1        |
|              3 | 20       | 2        |
|              4 | 45       | 1        |
|              5 | 45       | 2        |
|              6 | 15       | 3        |
+----------------+----------+----------+
6 rows in set (0.00 sec)

es decir, la tabla relaciones guarda sólo el id de las tablas catálogos. Esto es la esencia de un modelo Entidad-Relación...

Si puedes cambiar tu modelo HAZLO y evita dolores de cabeza... Si no puedes cambiar tu modelo, entonces tienes un problema bastante grave y me explico.

Tal como planteas que guardas los datos es decir, los id's separados por comas, entonces seguramente lo tienes definido como tipo VARCHAR. para buscar entonces los videos de un id_canal en especifico NO TE SIRVEN LAS COMPARACIONES TIPO IN. veamos por qué:

supongamos que tu tabla es así:

1
2
3
4
5
6
7
8
9
10
11
mysql> SELECT * FROM videos;
+----+----------+----------+--------------+
| id | id_canal | campo1   | campo2       |
+----+----------+----------+--------------+
| 19 | 1        | video 19 | campo basura |
| 20 | 1,2      | video 20 | campo basura |
| 45 | 2,1,3    | video 45 | campo basura |
| 45 | 2,3,1    | video 45 | campo basura |
| 45 | 11       | video 45 | campo basura |
+----+----------+----------+--------------+
5 rows in set (0.01 sec)

entonces, si quisieras buscar los videos del id_canal = 1, el IN NO "FUNCIONA" correctamente

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> SELECT * FROM videos WHERE id_canal IN (1);
+----+----------+----------+--------------+
| id | id_canal | campo1   | campo2       |
+----+----------+----------+--------------+
| 19 | 1        | video 19 | campo basura |
| 20 | 1,2      | video 20 | campo basura |
+----+----------+----------+--------------+
2 rows in set, 2 warnings (0.00 sec)
 
mysql> SELECT * FROM videos WHERE id_canal IN ('1');
+----+----------+----------+--------------+
| id | id_canal | campo1   | campo2       |
+----+----------+----------+--------------+
| 19 | 1        | video 19 | campo basura |
+----+----------+----------+--------------+
1 row in set (0.00 sec)

es decir, aun buscando como número o como letra, los casos en donde no está el número al INICIO de la secuencia no se muestran. Tampoco te serviría una comparación tipo LIKE '%1%', porque podría traer casos de más:

1
2
3
4
5
6
7
8
9
10
11
mysql> SELECT * FROM videos WHERE id_canal LIKE '%1%';
+----+----------+----------+--------------+
| id | id_canal | campo1   | campo2       |
+----+----------+----------+--------------+
| 19 | 1        | video 19 | campo basura |
| 20 | 1,2      | video 20 | campo basura |
| 45 | 2,1,3    | video 45 | campo basura |
| 45 | 2,3,1    | video 45 | campo basura |
| 45 | 11       | video 45 | campo basura |
+----+----------+----------+--------------+
5 rows in set (0.00 sec)

entonces, tendrías que usar comparaciones tipo LIKE para cada caso: cuando el id que buscas sea único, cuando esté al inicio, cuando esté en medio y cuando esté al final de la cadena:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> SELECT *
    -> FROM videos
    -> WHERE
    ->    id_canal = '1'
    -> OR id_canal LIKE  '1,%'
    -> OR id_canal LIKE  '%,1,%'
    -> OR id_canal LIKE  '%,1'
+----+----------+----------+--------------+
| id | id_canal | campo1   | campo2       |
+----+----------+----------+--------------+
| 19 | 1        | video 19 | campo basura |
| 20 | 1,2      | video 20 | campo basura |
| 45 | 2,1,3    | video 45 | campo basura |
| 45 | 2,3,1    | video 45 | campo basura |
+----+----------+----------+--------------+
4 rows in set (0.00 sec)

¿Se entiende el problema? Entonces insisto, si puedes cambiar tu modelo HAZLO.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar

Creo que mi consulta no esta bien del todo

Publicado por Rocko3000 (4 intervenciones) el 08/06/2018 19:25:26
Hola leonardo!
Muchas gracias por tu explicación tan clara, seguire tu consejo y cambiare el modelo.

otra vez gracias!
saludos :)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar