Ir al contenido
wannacode

Tipos de relación: 1:1, 1:N, M:N

En resumen: Una relación entre dos tablas es uno a uno, uno a muchos o muchos a muchos, y su tipo decide dónde va la clave foránea y cuándo necesitas una tabla de enlace.

Problema

Una tarjeta y etiquetas

La tienda lanza dos novedades. La primera es una tarjeta de fidelidad: cada cliente puede tener una tarjeta con puntos. La segunda son las etiquetas de los productos, como «vegano», «sin gluten» y «ecológico», para que la web pueda filtrar por ellas.

¿Dónde las guardas? ¿Una columna card_number en customers? ¿Una columna tags en products con el texto «vegano, ecológico»? La respuesta depende de una pregunta: cuántas cosas de un lado corresponden a cuántas del otro.

La idea

Uno a muchos (1:N)

Un cliente tiene muchos pedidos. Cada pedido pertenece a un cliente. Es una relación uno a muchos, que se escribe 1:N.

La clave va en el lado «muchos». Cada pedido dice de quién es con customer_id:

customers

  • PKidinteger
  • nametext *
  • emailtext *
  • citytext
  • joined_attext *

orders

  • PKidinteger
  • FKcustomer_idinteger *→ customers
  • ordered_attext *
  • statustext *

Al revés no funciona. ¿Cuántas columnas order_1, order_2 debería tener un cliente? María tiene 12 pedidos, y mañana tendrá 13.

SQLbase de datos: tienda

Es la relación más común. En la tienda, una categoría y sus productos son así, y también un producto y sus reseñas.

Pruébalo

Productos por categoría

¿Cuántos productos hay en cada categoría que tiene productos? Muestra el nombre de la categoría y la cantidad.

SQLbase de datos: tienda

La idea

Uno a uno (1:1)

Cada cliente tiene como máximo una tarjeta, y cada tarjeta pertenece a un cliente. Es uno a uno, 1:1. Se guarda como 1:N, con una clave hacia el cliente, más una regla extra: UNIQUE.

loyalty_cards

  • PKidinteger
  • FKcustomer_idinteger *→ customers
  • numbertext *
  • pointsinteger *
  • issued_attext *
SQLbase de datos: tienda

Cinco clientes tienen tarjeta. Prueba a darle una segunda a María:

SQLbase de datos: tienda

UNIQUE en customer_id no deja entrar una segunda fila para el mismo cliente. Sin él, la relación sería 1:N.

¿Por qué no columnas en customers? También funciona. A menudo 1:1 son simplemente más columnas en la misma tabla. Una tabla aparte tiene sentido cuando la mayoría de las filas no tienen la segunda parte (15 de los 20 clientes no tienen tarjeta y tendrían celdas vacías), o cuando tiene vida propia: la tarjeta se pierde, se reemplaza, tiene sus propios puntos.

Pruébalo

Quién todavía no tiene tarjeta

Marketing quiere ofrecer una tarjeta a cada cliente que todavía no tiene. Muestra sus nombres.

SQLbase de datos: tienda

La idea

Muchos a muchos (M:N)

Un pedido tiene muchos productos. Un producto está en muchos pedidos. Es muchos a muchos, M:N.

Aquí la clave no puede ir en ninguna de las dos tablas. La solución es una tercera tabla, una tabla de enlace, con una fila por cada pareja. En la tienda es order_items: cada fila es un producto en un pedido, con la cantidad y el precio.

products

  • PKidinteger
  • nametext *
  • FKcategory_idinteger→ categories
  • pricereal *
  • stockinteger *
  • added_attext *

order_items

  • PKorder_idinteger→ orders
  • PKproduct_idinteger→ products
  • quantityinteger *
  • unit_pricereal *

¿Qué pedidos llevan el café (producto 17)?

SQLbase de datos: tienda

Con las etiquetas pasa lo mismo. Un producto tiene muchas etiquetas, y una etiqueta está en muchos productos:

tags

  • PKidinteger
  • nametext *

product_tags

  • PKproduct_idinteger→ products
  • PKtag_idinteger→ tags
SQLbase de datos: tienda

Míralo

La pareja es la clave

La clave primaria de order_items es la pareja (order_id, product_id). Prueba a añadir el pan por segunda vez al pedido 60, que ya lo tiene:

SQLbase de datos: tienda

La base de datos no permite la misma pareja dos veces. Un producto está en el pedido una vez, y las piezas de más van en quantity. Si no, el informe «cuántas veces se pidió el pan» contaría dos veces el mismo producto de un pedido.

1. Cada producto tiene exactamente una categoría, y una categoría tiene muchos productos. ¿Dónde va la clave?

Pruébalo

Etiquetas en la web

Junto a cada etiqueta, la web muestra cuántos productos la tienen. Muestra el nombre de la etiqueta y la cantidad.

SQLbase de datos: tienda

Ejercicio

Dos tareas

1. La página de las manzanas muestra sus etiquetas. ¿Cuáles son?

Las etiquetas del producto «Manzanas»:

SQLbase de datos: tienda

2. Un cliente busca productos que sean a la vez veganos y sin gluten. Muestra sus nombres.

Los productos con las dos etiquetas, «vegano» y «sin gluten»:

SQLbase de datos: tienda

Test

Ponte a prueba

1. ¿Qué hace que la relación entre loyalty_cards y customers sea 1:1 y no 1:N?
2. Un estudiante cursa muchas asignaturas, y una asignatura tiene muchos estudiantes. ¿Cómo lo guardas?
3. ¿Por qué la clave primaria de product_tags es (product_id, tag_id)?
4. ¿Por qué la consulta con WHERE t.name = 'vegano' AND t.name = 'sin gluten' no encuentra nada?

Creado por Ivo Gergov como parte de la campaña de Evo Tech por una educación accesible en programación ·