php mysql database-design mapping categories

php - MySQL: comprensión de las tablas de asignación



database-design mapping (4)

Cuando construyo un sistema de navegación de categoría para un directorio de negocios con una relación de muchos a muchos, entiendo que es una buena práctica crear una tabla de mapeo.

Tabla de categoría (CategoryId, CategoryName)
Business Table (BusinessId, BusinessName)
Tabla de asignación de categorías (ID de empresa, ID de categoría)

Cuando me una a la tabla de Categoría y a la tabla de Negocios para crear la tabla de asignación, ¿esto me daría una tabla que contiene todas las relaciones comerciales y de categoría posibles?

Tengo 800 categorías y 1000 listas de negocios. Eso me daría una tabla que contiene 800,000 posibles relaciones. Si es así, ¿cómo me enfocaría solo en las relaciones que existen? ¿Tendría que revisar todas las listas (800,000) marcándolas como verdaderas o falsas?

Me he sentido realmente confundido acerca de esto, por lo que cualquier ayuda sería muy apreciada.


Cuando me una a la tabla de Categoría y a la tabla de Negocios para crear la tabla de asignación, ¿esto me daría una tabla que contiene todas las relaciones comerciales y de categoría posibles?

Sí.

¿Tendría que revisar todas las listas (800,000) marcándolas como verdaderas o falsas?

No, debe usar la cláusula ON para establecer condiciones de unión.

SELECT <columns> FROM categories as c INNER JOIN mapping AS m ON m.CategoryId = c.CategoryId INNER JOIN businesses as b ON m.BusinessId = b.BusinessId


Debe usar tablas de asignación cuando intente modelar una relación de muchos a muchos o de uno a muchos.

Por ejemplo, en una aplicación de libreta de direcciones, un contacto en particular podría pertenecer a cero, una o varias categorías. Si establece su lógica comercial de que un contacto solo puede pertenecer a una categoría, debe definir su contacto como:

Contact -------------- contactid (PK) name categoryid (FK) Category -------------- categoryid (PK) categoryname

Pero si desea permitir que un contacto tenga más de una dirección de correo electrónico, use una tabla de asignación:

Contact -------------- contactid (PK) name Category -------------- categoryid (PK) categoryname Contact_Category -------------- contactid (FK) categoryid (FK)

Luego puede usar SQL para recuperar una lista de categorías a las que está asignado un contacto:

seleccione a.categoryname de la Categoría a, Contacto b, Contact_Category c donde a.categoryid = c.categoryid y b.contactid = c.contactid y b.contactid = 12345;

select a.categoryname from Category a inner join Contact_Category c on a.categoryid=c.categoryid inner join Contact b on b.contactid=c.contactid where b.contactid=12345;


usted solo pone las relaciones reales en la tabla de mapeo. Entonces, en promedio, una empresa está en 2 categorías, luego en su ejemplo, solo habría 2000 registros en la tabla de asignación, no 800,000

"Cuando me uno a la tabla Category y Business para crear la tabla de asignación" no se unen esas dos tablas para crear la tabla de asignación. Usted crea una tabla física real.


Al usar relaciones de muchos a muchos, la única manera realista de manejar esto es con una tabla de asignación.

Digamos que tenemos una escuela con maestros y estudiantes, un estudiante puede tener múltiples maestros y viceversa.

Entonces hacemos 3 tablas

student id unsigned integer auto_increment primary key name varchar teacher id unsigned integer auto_increment primary key name varchar link_st student_id integer not null teacher_id integer not null primary key (student_id, teacher_id)

La mesa de estudiantes tendrá 1000 registros
La mesa del maestro tendrá 20 registros
La tabla link_st tendrá tantos registros como enlaces (NO 20x1000, pero solo para los enlaces reales).

Selección
Selecciona, por ejemplo, alumnos por profesor usando:

SELECT s.name, t.name FROM student INNER JOIN link_st l ON (l.student_id = s.id) <--- first link student to the link-table INNER JOIN teacher t ON (l.teacher_id = t.id) <--- then link teacher to the link table. ORDER BY t.id, s.id

Normalmente siempre deberías usar una inner join aquí.

Hacer un enlace
Cuando asigna un profesor a un alumno (o viceversa, es lo mismo) . Solo necesitas hacer:

INSERT INTO link_st (student_id, teacher_id) SELECT s.id, t.id FROM student s INNER JOIN teacher t ON (t.name = ''Jones'') WHERE s.name = ''kiddo''

Esto es un mal uso de una unión interna, pero funciona siempre que los nombres sean únicos.
Si conoce las identificaciones, puede insertarlas directamente, por supuesto.
Si los nombres no son únicos, esto será un error y no se debe usar.

Cómo evitar enlaces duplicados
Es muy importante evitar enlaces duplicados, todo tipo de cosas malas sucederán si las tienes.
Si desea evitar la inserción de enlaces duplicados a su tabla de enlaces, puede declarar un índice unique en el enlace (recomendado)

ALTER TABLE link_st ADD UNIQUE INDEX s_t (student_id, teacher_id);

O puede hacer el control en la declaración de inserción (no muy recomendable, pero funciona).

INSERT INTO link_st (student_id, teacher_id) SELECT s.id, t.id FROM student s INNER JOIN teacher t ON (t.id = 548) LEFT JOIN link_st l ON (l.student_id = s.id AND l.teacher_id = t.id) WHERE (s.id = 785) AND (l.id IS NULL)

Esto solo seleccionará 548, 785 si esos datos no están ya en la tabla link_st , y no devolverá nada si esos datos ya están en link_st. Por lo tanto, se negará a insertar valores duplicados.

Si tiene una escuela de mesa, depende si un estudiante puede inscribirse en varias escuelas (poco probable, pero asumamos) y los maestros pueden inscribirse en varias escuelas. Muy posible.

table school id unsigned integer auto_increment primary key name varchar table school_members id id unsigned integer auto_increment primary key school_id integer not null member_id integer not null is_student boolean not null

Puede enumerar a todos los estudiantes en una escuela así:

SELECT s.name FROM school i INNER JOIN school_members m ON (i.id = m.school_id) INNER JOIN student s ON (s.id = m.member_id AND m.is_student = true)