Tengo una Competitions
tabla de resultados que contiene los nombres de los miembros del equipo y su clasificación por un lado.
Por otro lado, necesito mantener una tabla de nombres de competidores únicos :
CREATE TABLE Competitors (cName nvarchar(64) primary key)
Ahora tengo unos 200,000 resultados en la primera tabla y cuando la tabla de competidores está vacía puedo realizar esto:
INSERT INTO Competitors SELECT DISTINCT Name FROM CompResults
Y la consulta solo lleva unos 5 segundos para insertar unos 11,000 nombres.
Hasta ahora, esta no es una aplicación crítica, por lo que puedo considerar truncar la tabla Competidores una vez al mes, cuando reciba los nuevos resultados de la competencia con unas 10,000 filas.
Pero, ¿cuál es la mejor práctica cuando se agregan nuevos resultados, con competidores nuevos Y existentes? No quiero truncar la tabla de competidores existentes
Necesito realizar la declaración INSERT solo para nuevos competidores y no hacer nada si existen.
fuente
NVARCHAR(64)
columna su clave principal (y por lo tanto: agrupación)! En primer lugar, es una clave muy amplia , hasta 128 bytes; y en segundo lugar, es de tamaño variable, de nuevo: no es óptimo ... Esta es la peor opción que puede tener: su rendimiento será un infierno, y la fragmentación de tablas e índices estará en 99.9% todo el tiempo .....cName
falla en tres de cuatro categorías .... (no es estrecho, es probable que no es estático, y es definitivamente no siempre creciente)Respuestas:
Semánticamente está preguntando "insertar competidores donde aún no existe":
fuente
Otra opción es unirse a la tabla de resultados con la tabla de competidores existentes y encontrar a los nuevos competidores filtrando los registros distintos que no coinciden en la combinación:
La nueva sintaxis MERGE también ofrece una forma compacta, elegante y eficiente de hacer eso:
fuente
No sé por qué nadie más ha dicho esto todavía;
NORMALIZAR.
¿Tienes una mesa que modela competiciones? Las competiciones están formadas por competidores? Necesita una lista distinta de competidores en una o más competiciones ......
Deberías tener las siguientes tablas .....
Con Restricciones en CompetitionCompetitors.CompetitionID y CompetitorID apuntando a las otras tablas.
Con este tipo de estructura de tabla, sus teclas son simples INTS, no parece haber una buena CLAVE NATURAL que se ajuste al modelo, por lo que creo que una CLAVE SURROGATE encaja bien aquí.
Entonces, si tenía esto, para obtener la lista distintiva de competidores en una competencia en particular, puede emitir una consulta como esta:
Y si quería el puntaje para cada competencia en la que se encuentra un competidor:
Y cuando tiene una nueva competencia con nuevos competidores, simplemente verifique cuáles ya existen en la tabla Competidores. Si ya existen, no se inserta en el competidor para esos competidores y sí se inserta para los nuevos.
Luego inserta la nueva Competencia en Competencia y finalmente crea todos los enlaces en Competidores.
fuente
Deberá unirse a las tablas y obtener una lista de competidores únicos que aún no existen
Competitors
.Esto insertará registros únicos.
Puede llegar un momento en que esta inserción deba realizarse rápidamente sin poder esperar la selección de nombres únicos. En ese caso, puede insertar los nombres únicos en una tabla temporal y luego usar esa tabla temporal para insertar en su tabla real. Esto funciona bien porque todo el procesamiento ocurre en el momento en que se inserta en una tabla temporal, por lo que no afecta a su tabla real. Luego, cuando haya terminado todo el procesamiento, realice una inserción rápida en la tabla real. Incluso podría envolver la última parte, donde se inserta en la tabla real, dentro de una transacción.
fuente
¡Las respuestas anteriores que hablan sobre normalización son geniales! Pero, ¿qué pasa si te encuentras en una posición como yo donde no puedes tocar el esquema o la estructura de la base de datos tal como está? Por ejemplo, los DBA son 'dioses' y todas las revisiones sugeridas van a / dev / null?
En ese sentido, siento que esto también se ha respondido con esta publicación de Stack Overflow en lo que respecta a todos los usuarios anteriores que dan ejemplos de código.
Estoy volviendo a publicar el código de INSERTAR VALORES DONDE NO EXISTE, lo que me ayudó más, ya que no puedo alterar ninguna tabla de base de datos subyacente:
El código anterior usa campos diferentes de los que tiene, pero obtiene la esencia general con las diversas técnicas.
Tenga en cuenta que según la respuesta original en Stack Overflow, este código se copió desde aquí .
De todos modos, mi punto es que la "mejor práctica" a menudo se reduce a lo que puedes y no puedes hacer tan bien como a la teoría.
¡Buena suerte!
fuente
Normalizar sus tablas operativas como lo sugiere Transact Charlie, es una buena idea, y ahorrará muchos dolores de cabeza y problemas con el tiempo, pero existen tablas de interfaz , que admiten la integración con sistemas externos, y tablas de informes , que admiten cosas como análisis Procesando; y esos tipos de tablas no necesariamente deben normalizarse ; de hecho, muy a menudo es mucho, mucho más conveniente y eficaz para que no lo sean .
En este caso, creo que la propuesta de Transact Charlie para sus tablas operativas es buena.
Pero agregaría un índice (no necesariamente único) a CompetitorName en la tabla Competidores para admitir uniones eficientes en CompetitorName con fines de integración (carga de datos de fuentes externas), y pondría una tabla de interfaz en la mezcla: CompeticiónResultados.
Los resultados de la competencia deben contener los datos que contengan los resultados de su competencia. El objetivo de una tabla de interfaz como esta es hacer que sea lo más rápido y fácil posible truncar y volver a cargarlo desde una hoja de Excel o un archivo CSV, o cualquier forma en la que tenga esos datos.
Esa tabla de interfaz no debe considerarse parte del conjunto normalizado de tablas operativas. Luego puede unirse a CompetResults como lo sugiere Richard, para insertar registros en Competidores que aún no existen, y actualizar los que sí existen (por ejemplo, si realmente tiene más información sobre competidores, como su número de teléfono o dirección de correo electrónico).
Una cosa que señalaría: en realidad, el nombre de la competencia, me parece, es muy poco probable que sea único en sus datos . En 200,000 competidores, es muy posible que tenga 2 o más David Smiths, por ejemplo. Por lo tanto, le recomendaría que recopile más información de los competidores, como su número de teléfono o una dirección de correo electrónico, o algo que sea más probable que sea único.
Su tabla operativa, Competidores, solo debe tener una columna para cada elemento de datos que contribuya a una clave natural compuesta; por ejemplo, debe tener una columna para una dirección de correo electrónico principal. Pero la tabla de interfaz debe tener un espacio para los valores antiguos y nuevos para una dirección de correo electrónico principal, de modo que el valor anterior se pueda usar para buscar el registro en Competidores y actualizar esa parte al nuevo valor.
Por lo tanto, los resultados de la competencia deben tener algunos campos "antiguos" y "nuevos": correo electrónico antiguo, correo electrónico nuevo, teléfono antiguo, teléfono nuevo, etc. De esa manera puede formar una clave compuesta, en Competidores, desde Nombre de competidor, Correo electrónico y Teléfono.
Luego, cuando tenga algunos resultados de la competencia, puede truncar y volver a cargar su tabla de Resultados de Competencia desde su hoja de Excel o lo que sea que tenga, y ejecutar una inserción única y eficiente para insertar a todos los nuevos competidores en la tabla de Competidores, y una actualización única y eficiente para actualizar toda la información sobre los competidores existentes de los Resultados de la competencia. Y puede hacer una sola inserción para insertar nuevas filas en la tabla CompetitionCompetitors. Estas cosas se pueden hacer en un procedimiento almacenado ProcessCompetitionResults, que se puede ejecutar después de cargar la tabla CompetitionResults.
Esa es una especie de descripción rudimentaria de lo que he visto hacer una y otra vez en el mundo real con Oracle Applications, SAP, PeopleSoft y una larga lista de otras suites de software empresarial.
Un último comentario que haría es uno que he hecho antes sobre SO: si crea una clave foránea que asegura que existe un competidor en la tabla de competidores antes de poder agregar una fila con ese competidor en CompetitionCompetitors, asegúrese de que la clave externa se establece en actualizaciones y eliminaciones en cascada . De esa manera, si necesita eliminar un competidor, puede hacerlo y todas las filas asociadas con ese competidor se eliminarán automáticamente. De lo contrario, de forma predeterminada, la clave externa requerirá que elimine todas las filas relacionadas de CompetCompetitors antes de permitirle eliminar un Competidor.
(Algunas personas piensan que las claves externas no en cascada son una buena precaución de seguridad, pero mi experiencia es que solo son un dolor en el trasero que con frecuencia son simplemente el resultado de un descuido y crean un montón de trabajo). para DBA. Al tratar con personas que eliminan accidentalmente cosas, es por eso que tiene cosas como cuadros de diálogo "¿está seguro?" y varios tipos de copias de seguridad regulares y fuentes de datos redundantes. Es mucho, mucho más común querer eliminar un competidor, cuyos datos son todos en mal estado, por ejemplo, que eliminar accidentalmente uno y luego decir "¡Oh, no! ¡No quise hacer eso! ¡Y ahora no tengo los resultados de su competencia! ¡Aaaahh!" , debes estar preparado para ello, pero el primero es mucho más común,así que la manera más fácil y mejor de prepararse para la primera, imo, es simplemente realizar actualizaciones y eliminaciones en cascada de claves foráneas).
fuente
Ok, esto se preguntó hace 7 años, pero creo que la mejor solución aquí es renunciar a la nueva tabla por completo y hacer esto como una vista personalizada. De esa forma no está duplicando datos, no hay que preocuparse por datos únicos y no toca la estructura de la base de datos real. Algo como esto:
Aquí se pueden agregar otros elementos, como combinaciones en otras tablas, cláusulas WHERE, etc. Esta es probablemente la solución más elegante para este problema, ya que ahora puede consultar la vista:
... y agregue cualquier cláusula WHERE, IN o EXISTS a la consulta de vista.
fuente