0

Datos tabla Productos

introducir la descripción de la imagen aquí Esta es la consulta que deseo pero no me arroja datos.

SELECT
p.id,
p.nombre,
p.descripcion,
p.precio,
p.marca_id,
p.categoria_id
FROM
producto p, marca m, categoria c
WHERE  p.marca_id=m.nombre
AND p.categoria_id=c.nombre
AND  Upper(p.nombre) LIKE upper ('%so%');

introducir la descripción de la imagen aquí

Ahora esta consulta si me arroja datos.

SELECT
p.id,
p.nombre,
p.descripcion,
p.precio,
p.marca_id,
p.categoria_id
FROM
producto p, marca m, categoria c
WHERE  p.marca_id=m.id
AND p.categoria_id=c.id
AND  Upper(p.nombre) LIKE upper ('%so%');

introducir la descripción de la imagen aquí

Me doy cuenta que solo reconoce las llaves primarias de cada tabla.

DDL Del workspace

CREATE TABLE categoria (
id       VARCHAR2(25 CHAR) NOT NULL,
nombre   VARCHAR2(50 CHAR)
);

ALTER TABLE categoria ADD CONSTRAINT categoria_pk PRIMARY KEY ( id );

CREATE TABLE marca (
id       VARCHAR2(25 CHAR) NOT NULL,
nombre   VARCHAR2(50 CHAR)
);

ALTER TABLE marca ADD CONSTRAINT marca_pk PRIMARY KEY ( id );

CREATE TABLE producto (
id             VARCHAR2(50 CHAR) NOT NULL,
nombre         VARCHAR2(50 CHAR),
descripcion    VARCHAR2(100 CHAR),
precio         VARCHAR2(100 CHAR),
marca_id       VARCHAR2(25 CHAR) NOT NULL,
categoria_id   VARCHAR2(25 CHAR) NOT NULL
);

ALTER TABLE producto ADD CONSTRAINT producto_pk PRIMARY KEY ( id );

CREATE TABLE usuario (
nombre       VARCHAR2(50 CHAR),
correo       VARCHAR2(50 CHAR),
contraseña   VARCHAR2(25 CHAR) NOT NULL
);

ALTER TABLE usuario ADD CONSTRAINT usuario_pk PRIMARY KEY ( contraseña );

ALTER TABLE producto
ADD CONSTRAINT producto_categoria_fk FOREIGN KEY ( categoria_id )
    REFERENCES categoria ( id );

ALTER TABLE producto
ADD CONSTRAINT producto_marca_fk FOREIGN KEY ( marca_id )
    REFERENCES marca ( id );

ALTER TABLE producto
ADD CONSTRAINT producto_categoria_fk FOREIGN KEY ( categoria_id )
    REFERENCES categoria ( id );

ALTER TABLE producto
ADD CONSTRAINT producto_marca_fk FOREIGN KEY ( marca_id )
    REFERENCES marca ( id );

Espero me ayuden a cumplir mi objetivo. Gracias.

WilsonPT
  • 657
  • 3
  • 10
  • 2
    La consulta que mostraste en la segunda parte está bien, es como deberías realizar la consulta. Ya que la tabla producto solo contiene como referencia (FK) la llave primaria (PK) de otra tabla solo puedes compararlos mediante el Id. No con el nombre ya que ese atributo es ajeno a tu tabla producto. Saludos! – Gian Marco Carrasco Vasquez Apr 04 '19 at 18:02

3 Answers3

2

Creo que nos enfrentamos a un problema básico de concepto.

En primer lugar, estás escribiendo tus queries con una sintaxis que es anterior al estándar sql-92 (si, de 1992, ¡hace casi 30 años!). Si bien Oracle es de los fabricantes que más se han tardado en incorporar el estándar, estoy seguro que ya Oracle 9i la soportaba, y probablemente Oracle 8 (de 1997) también lo hacía.

Hablemos de la forma moderna de escribir un query, utilizando la sintaxis de join explícito.

Intentaré explicarte lo que un join es, y para ello partiremos del join más básico que hay, que es el producto cartesiano de dos tablas (o conjuntos de datos en general)1.

Por ejemplo, si tengo un par de tablas tabla1 y tabla2, con esta información:

tabla1

número  letra 
======  ======
1       a
2       b

tabla2

número  letra 
======  ======
1       x
2       y

Y hago un cross join entre ambas:

select tabla1.numero, tabla2.letra
  from tabla1
       cross join tabla2

numero letra
====== =====
     1 x
     1 y
     2 x
     2 y

Si no lo has hecho, te recomiendo leer el artículo enlazado sobre el producto cartesiano, y volver a este punto cuando hayas comprendido dicha operación.

Cuando haces una operación inner/outer join, en un query, lo que defines son las condiciones por las cuales el motor debe considerar que ha encontrado una coincidencia en un par de registros que cumple la condición del join, dentro de dicho producto cartesiano.

Tu, como autor del query, puedes definir cualquier condición que quieras. La única regla es que dicha condición se pueda evaluar como un valor booleano, es decir, que evalúe a verdadero o falso.

Por ejemplo, yo puedo hacer esto:

select tabla1.numero, tabla2.letra
  from tabla1
       inner join tabla2 on 1 = 1

Dado que la condición 1 = 1 (uno es igual a uno) siempre es verdadera (sin importar los valores de cada uno de los registros de las tablas), esto me devolverá el mismo resultado del cross join: el producto cartesiano de las tablas:

numero letra
====== =====
     1 x
     1 y
     2 x
     2 y

El motor de base de datos no intentará juzgar si la expresión que has colocado como parte del join es correcta en términos del dominio del problema que intentas resolver. El motor se limita a evaluar la condición para cada par posible de registros y e incluir aquellos registros para los que dicha expresión devuelva verdadero.

Por tanto, este join entregará el resultado que le sigue:

select tabla1.numero, tabla1.letra, tabla2.letra
  from tabla1
       inner join tabla2 on tabla1.numero = tabla2.numero

número  letra letra
======  ===== ====
1       a     x
2       b     y

Mientras que este otro:

select tabla1.numero, tabla1.letra, tabla2.letra
  from tabla1
       inner join tabla2 on tabla1.numero = tabla2.letra

No devolverá ninguno, o posiblemente devolverá un error, dependiendo del motor.

Si la expresión utilizada hace sentido, debes evaluarlo tu.

Aterrizando todo esto:

Entonces, sobre tu pregunta, ¿por qué la condición p.marca_id = m.nombre no devuelve ningún resultado, mientras que p.marca_id = m.id si lo hace?

Visto desde el motor de base de datos, la respuesta simple es:

Porque no hay ningún par de registros que marquen una coincidencia a dicha condición, es decir, donde p.marca_id sea igual a m.nombre, mientras que si hay pares de registros que cumplen con la condición que p.marca_id sea igual a m.id.


1 Un cross join, a diferencia de inner/outer join no requiere especificar ninguna condición, pues siempre devolverá el producto cartesiano de ambos conjuntos de datos.

jachguate
  • 25,659
  • 7
  • 35
  • 61
0

Cuando realices un JOIN debes de vincular las tablas por medio de las llaves foráneas, no puedes vincular las tablas con cualquier columna, ya que sinó no te va a devolver valores

  • 1
    Si bien tu respuesta puede dar con la posible solución, es mejor agregar mas detalles al respecto como código que permita un mejor entendimiento a quien pregunta...gracias por responder..!! – Diego Avila Apr 04 '19 at 18:09
  • Un join no requiere que haya una llave foránea declarada entre las tablas. – jachguate Apr 04 '19 at 19:30
  • @jachguate entonces como sería para lograrlo? – WilsonPT Apr 04 '19 at 19:50
  • @Isaias, lee [mi respuesta](https://es.stackoverflow.com/a/251748/21), allí te lo explico con detalle. Un saludo. – jachguate Apr 04 '19 at 21:41
0

Puedes modificar tu consulta para que en tu join hagas referencia a las llaves foráneas de esta manera:

SELECT p.id, p.nombre, p.descripcion, p.precio, p.marca_id, p.categoria_id FROM producto p, marca m, categoria c WHERE p.marca_id = m.id AND p.categoria_id = c.id AND Upper(p.nombre) LIKE upper ('%so%');

Los join no necesariamente requieren que se comparen las llaves foráneas, pueden comparar otros campos en las tablas, pero solo en caso de que sean iguales (como en tu ejemplo) va a regresar resultados. Tu estabas comparando la llave foránea de categoría y marca en la tabla Producto con los campos nombre de las tablas categoría y marca, pero son tipos de datos destintos entonces nunca van a ser iguales (como indicas en tu cláusula WHERE). Saludos.

OrlandoMartinez
  • 326
  • 1
  • 6