Haré todo lo posible para explicar mi problema, sin embargo, la mayor parte de mi experiencia en SQL es autodidacta, así que por favor tengan paciencia conmigo.

Tengo una tabla [limit_table] que tiene una columna llamada [amount], sin embargo, esta columna limit_table.amount contiene una cantidad pero es para diferentes tipos de límites, el tipo de límite está determinado por una columna llamada LimitTypeid, que tiene una clave externa enlace a otra tabla [LimitType]

Limit_table también tiene un enlace de clave externa a una tabla [cliente].

Lo que estoy tratando de hacer es obtener el límite para cada cliente en la tabla [cliente] donde LimitType = x de esos resultados. También quiero saber si el cliente es LimitType de y incluso si no existe.

Por mi vida, ¿no puedo hacer que esto funcione? Cualquier puntero sería genial. He intentado unir / dejar la unión externa de nuevo en la tabla del cliente usando el client.id de la tabla del cliente, pero esto no parece funcionar.

Entonces LimitType X debe estar presente (puede ser cero pero no NULL) pero LimitType y es opcional.

Con la esperanza de terminar con resultados que se parecen básicamente a

Client   LimitTypeXAmount   LimitTypeYAmount
ClientA  15000.00           1000.00
ClientB  10000.00           NULL
ClientC  0                  1000.00

Aquí hay una consulta anterior que probé:

SELECT CL.CLIENT, LIM.AMOUNT AS LIMITTYPEXAMOUNT, LIM2.AMOUNT AS LIMITTYPEYAMOUNT, FROM CLIENT CL1 
INNER JOIN LIMIT LIM1 ON LIM1.CLIENTID = CL1.ID
INNER JOIN LIMITTYPE LT1 ON LIM1.LIMITTYPEID = LT1.ID AND LT1.TYPE = 'X'
LEFT OUTER JOIN CLIENT CL2 ON CL1.ID = CL2.ID
LEFT OUTER JOIN LIMIT LIM2 ON LIM2.CLIENTID = CL2.ID
LEFT OUTER JOIN LIMITTYPE LT2 ON LIM2.LIMITTYPEID = LT2.ID AND LT2.TYPE = 'Y'

Presunto esquema a continuación (agregado por la moderadora):

create table Client (Id int not null, Client varchar(10) not null);
create table Limit (Id int not null, ClientId int not null, Amount decimal (8, 2) not null, LimitTypeId int not null);
create table LimitType (Id int not null, Type char(1) not null);

insert into LimitType (Id, Type) values (1, 'X'), (2, 'Y');
insert into Client (Id, Client) values (1, 'ClientA'), (2, 'ClientB'), (3, 'ClientC');
insert into Limit (Id, ClientId, Amount, LimitTypeId) values
    (1, 1, 15000.00, 1), (2, 1, 1000.00, 2), -- ClientA  15000.00    1000.00
    (3, 2, 10000.00, 1),                     -- ClientB  10000.00       NULL
    (4, 3,     0.00, 1), (5, 3, 1000.00, 2)  -- ClientC      0.00    1000.00
;
0
Alan Thomas 15 nov. 2017 a las 20:50

2 respuestas

La mejor respuesta

No estoy completamente seguro de por qué tiene la tabla LIMITTYPE. Supongo que solo hay una fila en esa tabla con TYPE = 'Y'. Por lo tanto, conectarse a eso como una combinación interna primero debería incluir solo esa fila y luego puede vincular a la LIMITTYPEID apropiada. Lo que no tengo claro es por qué TYPE no es solo un atributo de LIMIT. Estabas haciendo referencia a dos instancias diferentes de la tabla CLIENT pero eso parece ser innecesario y lo eliminé.

select
c.Client, l1.Amount as LimitTypeXAmount, l2.Amount as LimitTypeYAmount
from
    Client c
    inner join Limit as l1 on l1.ClientId = c.Id
    inner join LimitType as lt1 on lt1.Id = l1.LimitTypeId and lt1.Type = 'X'
    inner join LimitType as lt2 on lt2.Type = 'Y'
    left outer join Limit as l2 on l2.ClientId = c.Id and l2.LimitTypeId = lt2.Id;

Suponiendo que funcione, podría reflejar la misma lógica en las tres combinaciones anteriores. Dejaré a esos solos.

Otro enfoque utiliza una tabla derivada:

-- derived table
SELECT
    C.CLIENT,
    L1.AMOUNT AS LIMITTYPEXAMOUNT,
    L2.LIMITTYPEYAMOUNT
FROM 
    CLIENT C 
    INNER JOIN LIMIT L1 ON L1.CLIENTID = C.ID
    INNER JOIN LIMITTYPE LT1 ON LT1.ID = L1.LIMITTYPEID
    LEFT OUTER JOIN (
        SELECT
            L.CLIENTID, L.AMOUNT AS LIMITTYPEYAMOUNT
        FROM 
            LIMIT L
            INNER JOIN LIMITTYPE LT ON LT.ID = L.LIMITTYPEID
        WHERE
            LT.TYPE = 'Y'
    ) AS L2 ON L2.CLIENTID = C.ID
WHERE
    LT1.TYPE = 'X';

Y solo por diversión, con outer apply:

-- outer apply
SELECT
    C.CLIENT,
    L1.AMOUNT AS LIMITTYPEXAMOUNT,
    L2.LIMITTYPEYAMOUNT
FROM 
    CLIENT C 
    INNER JOIN LIMIT L1 ON L1.CLIENTID = C.ID
    INNER JOIN LIMITTYPE LT1 ON LT1.ID = L1.LIMITTYPEID
    OUTER APPLY (
        SELECT
            L.AMOUNT AS LIMITTYPEYAMOUNT
        FROM 
            LIMIT L
            INNER JOIN LIMITTYPE LT ON LT.ID = L.LIMITTYPEID
        WHERE
            LT.TYPE = 'Y' AND L.CLIENTID = C.ID
    ) AS L2
WHERE
    LT1.TYPE = 'X';

Editar: Supongo que estoy un poco oxidado ya que tampoco reconocí inmediatamente esto como un problema de orden de unión. Aquí hay otro enfoque que puede estudiar. Tiene la ventaja de funcionar en algunos sistemas más antiguos donde otras opciones no están disponibles.

select
    c.Client, l1.Amount as LimitTypeXAmount, l2.Amount as LimitTypeYAmount
from
    Client c
    inner join Limit as l1
        inner join LimitType as lt1
            on lt1.Id = l1.LimitTypeId and lt1.Type = 'X'
        on l1.ClientId = c.Id

    left outer join Limit as l2
        inner join LimitType as lt2
            on l2.LimitTypeId = lt2.Id and lt2.Type = 'Y'    
        on l2.ClientId = c.Id;

Juega con él aquí: http://rextester.com/WJZ23471

0
shawnt00 16 nov. 2017 a las 17:27

Tu consulta no parece incorrecta. Corrija el error tipográfico LIM.AMOUNT a LIM1.AMOUNT. La segunda tabla de Cliente es inútil: LEFT OUTER JOIN CLIENT CL2, puede eliminar esa línea y reemplazar CL2 por CL1 en cualquier otro lugar.

0
itsLex 15 nov. 2017 a las 23:13