Principales respuestas
Campo de una u otra tabla

Pregunta
-
Hola, tengo una consulta con respecto a una consulta en SQL.
Mi duda es como puedo hacer para seleccionar un campo de una u otro tabla. Me trato de explicar un poco mejor, necesito seleccionar el valor de un campo en una u otra tabla dependiendo del valor de una tabla.
En particular tengo una tabla llamada "CuentaCorriente" la cual tiene un campo llamado "FkPersona" el cual guarda PK de un cliente o un proveedor, y otro campo llamado "tipo" del tipo string que almacena si se trata de un "Proveedor" o "Cliente". Lo que trato de hacer el seleccionar el campo "nombre" a la cual corresponde la FK que esta en la tabla "CuentaCorriente", pero el problema me surge cuando tengo que determinar si va a buscarlo en la tabla "Clientes" o "Proveedor".
¿Como podria hacer para determinar en que tabla va a buscar el valor?
Espero me puedan ayudar, gracias.
Respuestas
-
Algo en contra de este esquema es que no se puede usar referencia declarativa para enforzar que la relacion exista durante la creacion.
Otra forma seria creando una restriccion de valor por defecto y de chequeo en cada tabla, luego formar una vista de union de ambas tablas. Esto simplifica futuros queries entre ellas.
CREATE TABLE dbo.cuentaCorriente (id INT IDENTITY(1, 1), FkPersona INT, Cuenta VARCHAR(28), tipo VARCHAR(10) NOT NULL CHECK (tipo IN ('Cliente', 'Proveedor')) ); GO CREATE TABLE dbo.cliente (id INT, nombre VARCHAR(10), tipo AS 'Cliente' PERSISTED, CONSTRAINT chk_tipo_cliente CHECK (tipo = 'Cliente') ); GO CREATE TABLE dbo.proveedor (id INT, nombre VARCHAR(10), tipo AS 'Proveedor' PERSISTED, CONSTRAINT chk_tipo_proveedor CHECK (tipo = 'Proveedor') ); GO INSERT INTO cuentaCorriente (FkPersona, Cuenta, tipo ) VALUES (1, '0001', 'cliente' ), (1, '0002', 'proveedor' ); GO INSERT INTO cliente (id, nombre ) VALUES (1, 'juanCli' ), (2, 'Oscar' ), (3, 'Luis' ); INSERT INTO proveedor (id, nombre ) VALUES (1, 'juanPro' ), (2, 'Manolo' ); GO CREATE VIEW dbo.vw_ClienteProveedor WITH SCHEMABINDING AS SELECT id, nombre, tipo FROM dbo.cliente UNION ALL SELECT id, nombre, tipo FROM dbo.proveedor; GO SELECT * FROM cuentaCorriente c INNER JOIN dbo.vw_ClienteProveedor AS CP ON CP.id = c.id AND CP.tipo = C.tipo;
AMB
Some guidelines for posting questions...
AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas- Marcado como respuesta Federico32113 lunes, 6 de agosto de 2018 19:33
- Desmarcado como respuesta Federico32113 martes, 7 de agosto de 2018 19:14
- Propuesto como respuesta Pablo RubioModerator miércoles, 8 de agosto de 2018 14:48
- Marcado como respuesta Pablo RubioModerator viernes, 10 de agosto de 2018 15:10
-
Si ambas tablas suelen tener el mismo tipo de data en la clave primaria entonces puedes crear una tercera tabla donde tengas las columnas comunes a ambas entidades.
cliente-proveedor (supertipo) -> id, nombre, tipo ("Cliente", "Proveedor")
cliente (subtipo) -> (id, tipo ("Cliente"), otras columnas de interes y no comunes)
proveedor (subtipo) -> (id, tipo ("Proveedor"), otras columnas de interes y no comunes)Las tablas Cliente y Proveedor tendran una restriccion de clave foranea apuntando al supertipo (id, tipo) -> (id, tipo).
AMB
Some guidelines for posting questions...
AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas- Propuesto como respuesta Pablo RubioModerator lunes, 6 de agosto de 2018 16:24
- Marcado como respuesta Pablo RubioModerator viernes, 10 de agosto de 2018 15:10
-
Hola Federico32113:
Espero haber entendido bien tu escenario. Creo que es algo así:
CREATE TABLE cuentaCorriente (id INT IDENTITY(1, 1), FkPersona INT, Cuenta VARCHAR(28), tipo VARCHAR(10) ); GO CREATE TABLE cliente (id INT, nombre VARCHAR(10) ); GO CREATE TABLE proveedor (id INT, nombre VARCHAR(10) ); GO INSERT INTO cuentaCorriente (FkPersona, Cuenta, tipo ) VALUES (1, '0001', 'cliente' ), (1, '0002', 'proveedor' ); GO INSERT INTO cliente (id, nombre ) VALUES (1, 'juanCli' ), (2, 'Oscar' ), (3, 'Luis' ); INSERT INTO proveedor (id, nombre ) VALUES (1, 'juanPro' ), (2, 'Manolo' ); GO SELECT * FROM cuentaCorriente c LEFT JOIN cliente cli ON c.FkPersona = cli.id AND c.tipo = 'cliente' LEFT JOIN proveedor p ON c.FkPersona = p.id AND c.tipo = 'proveedor';
En la propia relación puedes establecer el tipado.
Un saludo
- Propuesto como respuesta Pablo RubioModerator lunes, 6 de agosto de 2018 16:24
- Marcado como respuesta Federico32113 lunes, 6 de agosto de 2018 19:33
Todas las respuestas
-
Si ambas tablas suelen tener el mismo tipo de data en la clave primaria entonces puedes crear una tercera tabla donde tengas las columnas comunes a ambas entidades.
cliente-proveedor (supertipo) -> id, nombre, tipo ("Cliente", "Proveedor")
cliente (subtipo) -> (id, tipo ("Cliente"), otras columnas de interes y no comunes)
proveedor (subtipo) -> (id, tipo ("Proveedor"), otras columnas de interes y no comunes)Las tablas Cliente y Proveedor tendran una restriccion de clave foranea apuntando al supertipo (id, tipo) -> (id, tipo).
AMB
Some guidelines for posting questions...
AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas- Propuesto como respuesta Pablo RubioModerator lunes, 6 de agosto de 2018 16:24
- Marcado como respuesta Pablo RubioModerator viernes, 10 de agosto de 2018 15:10
-
Hola Federico32113:
Espero haber entendido bien tu escenario. Creo que es algo así:
CREATE TABLE cuentaCorriente (id INT IDENTITY(1, 1), FkPersona INT, Cuenta VARCHAR(28), tipo VARCHAR(10) ); GO CREATE TABLE cliente (id INT, nombre VARCHAR(10) ); GO CREATE TABLE proveedor (id INT, nombre VARCHAR(10) ); GO INSERT INTO cuentaCorriente (FkPersona, Cuenta, tipo ) VALUES (1, '0001', 'cliente' ), (1, '0002', 'proveedor' ); GO INSERT INTO cliente (id, nombre ) VALUES (1, 'juanCli' ), (2, 'Oscar' ), (3, 'Luis' ); INSERT INTO proveedor (id, nombre ) VALUES (1, 'juanPro' ), (2, 'Manolo' ); GO SELECT * FROM cuentaCorriente c LEFT JOIN cliente cli ON c.FkPersona = cli.id AND c.tipo = 'cliente' LEFT JOIN proveedor p ON c.FkPersona = p.id AND c.tipo = 'proveedor';
En la propia relación puedes establecer el tipado.
Un saludo
- Propuesto como respuesta Pablo RubioModerator lunes, 6 de agosto de 2018 16:24
- Marcado como respuesta Federico32113 lunes, 6 de agosto de 2018 19:33
-
Algo en contra de este esquema es que no se puede usar referencia declarativa para enforzar que la relacion exista durante la creacion.
Otra forma seria creando una restriccion de valor por defecto y de chequeo en cada tabla, luego formar una vista de union de ambas tablas. Esto simplifica futuros queries entre ellas.
CREATE TABLE dbo.cuentaCorriente (id INT IDENTITY(1, 1), FkPersona INT, Cuenta VARCHAR(28), tipo VARCHAR(10) NOT NULL CHECK (tipo IN ('Cliente', 'Proveedor')) ); GO CREATE TABLE dbo.cliente (id INT, nombre VARCHAR(10), tipo AS 'Cliente' PERSISTED, CONSTRAINT chk_tipo_cliente CHECK (tipo = 'Cliente') ); GO CREATE TABLE dbo.proveedor (id INT, nombre VARCHAR(10), tipo AS 'Proveedor' PERSISTED, CONSTRAINT chk_tipo_proveedor CHECK (tipo = 'Proveedor') ); GO INSERT INTO cuentaCorriente (FkPersona, Cuenta, tipo ) VALUES (1, '0001', 'cliente' ), (1, '0002', 'proveedor' ); GO INSERT INTO cliente (id, nombre ) VALUES (1, 'juanCli' ), (2, 'Oscar' ), (3, 'Luis' ); INSERT INTO proveedor (id, nombre ) VALUES (1, 'juanPro' ), (2, 'Manolo' ); GO CREATE VIEW dbo.vw_ClienteProveedor WITH SCHEMABINDING AS SELECT id, nombre, tipo FROM dbo.cliente UNION ALL SELECT id, nombre, tipo FROM dbo.proveedor; GO SELECT * FROM cuentaCorriente c INNER JOIN dbo.vw_ClienteProveedor AS CP ON CP.id = c.id AND CP.tipo = C.tipo;
AMB
Some guidelines for posting questions...
AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas- Marcado como respuesta Federico32113 lunes, 6 de agosto de 2018 19:33
- Desmarcado como respuesta Federico32113 martes, 7 de agosto de 2018 19:14
- Propuesto como respuesta Pablo RubioModerator miércoles, 8 de agosto de 2018 14:48
- Marcado como respuesta Pablo RubioModerator viernes, 10 de agosto de 2018 15:10
-
-
Hola!
Según he entendido tu problema y revisando tu última pregunta, lo normal sería mantener las CuentasCorrientes unidas, sin embargo "la división" que preguntas dependerá realmente de los requerimientos de tu proyecto, pero generalmente irían en la misma tabla.
Saludos!
Roberto Pozo (colocolino73)
MVP SQL Server
Blog: angaroasoft
Please mark answered if I've answered your question and vote for it as helpful to help other user's find a solution quicker