Corso SQL Server

SQL Server lezione #04 Come recuperare i dati da due o più tabelle

 

Come recuperare i dati da due o più tabelle

Nell'ultima lezione si è appreso come creare insiemi di risultati che contengono i dati di una singola tabella. In questa lezione verrà illustrato come creare insiemi di risultati di dati provenienti da due o più tabelle. A tale scopo, è possibile utilizzare un join o una unione.

Come lavorare con i join interni

Un join consente di combinare le colonne di due o più tabelle in un unico set di risultati. Negli argomenti che seguono, si apprenderà come utilizzare il tipo più comune di join, un join interno. Più avanti nella lezione si apprenderà come utilizzare altri tipi di join.

Come codificare un join interno

L'esempio qui sotto presenta la sintassi esplicita per la codifica di un join interno. Come si vedrà più avanti in questa lezione, SQL Server fornisce anche una sintassi implicita che si può usare per codificare le giunzioni interne. Tuttavia, la sintassi mostrata è quella più frequente. Per unire i dati di due tabelle, si codificano i nomi delle due tabelle nella clausola FROM e nella clausola JOIN. FROM insieme alla parola chiave JOIN e a una frase ON specifica la condizione di unione. La condizione di unione indica il modo in cui le due tabelle devono essere confrontate. Nella maggior parte dei casi, vengono confrontate in base alla relazione tra la chiave primaria della prima tabella e una chiave esterna della seconda tabella. L'istruzione SELECT di questo esempio si uniscono i dati delle tabelle Venditori e Fatture in base alla chiave primaria della tabella Venditori e la colonna VendorID della tabella Fatture. Si noti che, poiché l'operatore equal viene utilizzato in questa condizione, il valore della colonna VendorID della colonna VendorID di una riga della tabella Vendors deve corrispondere al VendorID di una riga della tabella Invoices perché la riga sia inclusa nel set di risultati. In altre parole, solo i fornitori con una o più fatture saranno inclusi. Anche se la maggior parte dei join utilizzano l'operatore di uguaglianza, è bene sapere che è possibile confrontare due tabelle in base ad altre condizioni. In questo esempio, la tabella Venditori viene unita alla tabella Fatture utilizzando una colonna che ha lo stesso nome in entrambe le tabelle: VendorID. Per questo motivo, le colonne devono essere qualificate per indicare da quale tabella provengono. Come si può può vedere, si codifica il nome di una colonna qualificata inserendo il nome della tabella e un punto davanti al nome della colonna. Sebbene questo esempio utilizzi nomi di colonne qualificati solo nella condizione di unione, è necessario qualificare il nome di una colonna ovunque appaia nell'istruzione se nella dichiarazione lo stesso nome è presente in entrambe le tabelle. In caso contrario, SQL Server restituirà un errore indicando che il nome della colonna è ambiguo. Naturalmente, è possibile qualificare anche i nomi di colonna che non sono ambigui. Tuttavia, vi consiglio di farlo solo se serve a rendere più chiaro il vostro codice.

La sintassi esplicita per un join interno

    SELECT select_list
    FROM table_l
       [INNER] JOIN table_2
          ON join_condition_l
       [[INNER] JOIN table_3
          ON join_condition_2] ...
                

Un'istruzione SELECT che unisce le tabelle Fornitori e Fatture

    USE AP
    GO
    SELECT InvoiceNumber, VendorName
    FROM Vendors JOIN Invoices
        ON Vendors.VendorID = Invoices.VendorID;
                

La stessa istruzione SELECT che unisce le tabelle Fornitori e Fatture espressa con Fatture come tabella base

    USE AP
    GO
    SELECT InvoiceNumber, VendorName
    FROM Invoices JOIN Vendors
        ON Invoices.VendorID = Vendors.VendorID;
                

Descrizione

Quando e come utilizzare i nomi di correlazione

Quando si nominano le tabelle da unire nella clausola FROM, è possibile assegnare nomi temporanei alle tabelle, chiamati nomi di correlazione o alias di tabella. Per farlo, si usa la frase AS proprio come quando si assegna un alias a una colonna. È necessario utilizzare tale nome al posto del nome originale della tabella originale in tutta la query. La prima istruzione SELECT di questa figura unisce i dati della tabella Venditori e Fatture. In questo caso, a entrambe le tabelle sono stati assegnati nomi di correlazione che consistono in una sola lettera. Sebbene nomi di correlazione così brevi possano ridurre la di digitazione, possono anche rendere più difficile la lettura e la manutenzione di una query. Di conseguenza, si dovrebbero usare i nomi delle correlazioni solo quando semplificano o chiariscono la query. Il nome della correlazione usato nella seconda istruzione SELECT degli esempi qui sotto, semplifica il nome della tabella InvoiceLineltems in Lineltems. In questo modo, il nome più breve può essere usato per fare riferimento alla colonna lnvoiceID della tabella nella condizione di join. Anche se questo non migliora di molto la query in questo esempio, può avere un effetto notevole su una query che fa riferimento alla colonna lnvoiceLineltems più volte.

La sintassi per un join interno che utilizza nomi di correlazione

    SELECT select_list
    FROM table_l [AS] nl
       [INNER] JOIN table_2 [AS] n2
          ON nl.column_name operator n2.column_name
       [[INNER] JOIN table_3 [AS] n3
          ON n2.column_name operator n3.column_name] ...
                

Un join interno con nomi di correlazione che rendono la query più difficile da leggere

    USE AP
    GO                    
    SELECT InvoiceNumber, VendorName, InvoiceDueDate,
       InvoiceTotal - PaymentTotal - CreditTotal AS BalanceDue
    FROM Vendors AS v JOIN Invoices AS i
       ON v.VendorID = i.VendorID
    WHERE InvoiceTotal - PaymentTotal - CreditTotal > 0
    ORDER BY InvoiceDueDate DESC
                

Crea la tabella InvoiceLineItems

    USE AP
    GO
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE InvoiceLineItems(
        InvoiceID int NOT NULL,
        InvoiceSequence smallint NOT NULL,
        AccountNo int NOT NULL,
        InvoiceLineItemAmount money NOT NULL,
        InvoiceLineItemDescription varchar(100) NOT NULL,
        CONSTRAINT PK_InvoiceLineItems PRIMARY KEY CLUSTERED 
        (
            InvoiceID ASC,
            InvoiceSequence ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ) 
    GO
                

Inserisci le righe di InvoiceLineItems

    USE AP
    GO
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (1, 1, 553, 3813.3300, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (2, 1, 553, 40.2000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (3, 1, 553, 138.7500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (4, 1, 553, 144.7000, N'Int''l shipment')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (5, 1, 553, 15.5000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (6, 1, 553, 42.7500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (7, 1, 553, 172.5000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (8, 1, 522, 95.0000, N'Telephone service')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (9, 1, 403, 601.9500, N'Cover design')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (10, 1, 553, 42.6700, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (11, 1, 553, 42.5000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (12, 1, 580, 50.0000, N'DiCicco''s')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (12, 2, 570, 75.6000, N'Kinko''s')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (12, 3, 570, 58.4000, N'Office Max')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (12, 4, 540, 478.0000, N'Publishers Marketing')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (13, 1, 522, 16.3300, N'Telephone (line 5)')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (14, 1, 553, 6.0000, N'Freight out')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (15, 1, 574, 856.9200, N'Property Taxes')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (16, 1, 572, 9.9500, N'Monthly access fee')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (17, 1, 553, 10.0000, N'Address correction')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (18, 1, 553, 104.0000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (19, 1, 160, 116.5400, N'MVS Online Library')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (20, 1, 553, 6.0000, N'Freight out')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (21, 1, 589, 4901.2600, N'Office lease')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (22, 1, 553, 108.2500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (23, 1, 572, 9.9500, N'Monthly access fee')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (24, 1, 520, 1750.0000, N'Warehouse lease')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (25, 1, 553, 129.0000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (26, 1, 553, 10.0000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (27, 1, 540, 207.7800, N'Prospect list')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (28, 1, 553, 109.5000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (29, 1, 523, 450.0000, N'Back office additions')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (30, 1, 553, 63.4000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (31, 1, 589, 7125.3400, N'Web site design')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (32, 1, 403, 953.1000, N'Crash Course revision')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (33, 1, 591, 220.0000, N'Form 571-L')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (34, 1, 553, 127.7500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (35, 1, 507, 1600.0000, N'Income Tax')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (36, 1, 403, 565.1500, N'Crash Course Ad')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (37, 1, 553, 36.0000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (38, 1, 553, 61.5000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (39, 1, 400, 37966.1900, N'CICS Desk Reference')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (40, 1, 403, 639.7700, N'Card deck')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (41, 1, 553, 53.7500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (42, 1, 553, 400.0000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (43, 1, 400, 21842.0000, N'Book repro')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (44, 1, 522, 19.6700, N'Telephone (Line 3)')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (45, 1, 553, 2765.3600, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (46, 1, 510, 224.0000, N'Health Insurance')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (47, 1, 572, 1575.0000, N'Catalog ad')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (48, 1, 553, 33.0000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (49, 1, 522, 16.3300, N'Telephone (line 6)')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (50, 1, 510, 116.0000, N'Health Insurance')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (51, 1, 553, 2184.1100, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (52, 1, 160, 1083.5800, N'MSDN')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (53, 1, 522, 46.2100, N'Telephone (Line 1)')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (54, 1, 403, 313.5500, N'Card revision')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (55, 1, 553, 40.7500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (56, 1, 572, 2433.0000, N'Card deck')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (57, 1, 589, 1367.5000, N'401K Contributions')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (58, 1, 553, 53.2500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (59, 1, 553, 13.7500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (60, 1, 553, 2312.2000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (61, 1, 553, 25.6700, N'Freight out')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (62, 1, 553, 26.7500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (63, 1, 553, 2115.8100, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (64, 1, 553, 23.5000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (65, 1, 400, 6940.2500, N'OS Utilities')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (66, 1, 553, 31.9500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (67, 1, 553, 1927.5400, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (68, 1, 160, 936.9300, N'Quarterly Maintenance')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (69, 1, 540, 175.0000, N'Card deck advertising')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (70, 1, 553, 6.0000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (71, 1, 553, 108.5000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (72, 1, 553, 10.0000, N'Address correction')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (73, 1, 552, 290.0000, N'International pkg.')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (74, 1, 570, 41.8000, N'Coffee')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (75, 1, 553, 27.0000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (76, 1, 553, 241.0000, N'Int''l shipment')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (77, 1, 403, 904.1400, N'Cover design')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (78, 1, 403, 1197.0000, N'Cover design')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (78, 2, 540, 765.1300, N'Catalog design')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (79, 1, 540, 2184.5000, N'PC card deck')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (80, 1, 553, 2318.0300, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (81, 1, 553, 26.2500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (82, 1, 150, 17.5000, N'Supplies')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (83, 1, 522, 39.7700, N'Telephone (Line 2)')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (84, 1, 553, 111.0000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (85, 1, 553, 158.0000, N'Int''l shipment')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (86, 1, 553, 739.2000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (87, 1, 553, 60.0000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (88, 1, 553, 147.2500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (89, 1, 400, 85.3100, N'Book copy')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (90, 1, 553, 38.7500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (91, 1, 522, 32.7000, N'Telephone (line 4)')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (92, 1, 521, 16.6200, N'Propane-forklift')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (93, 1, 553, 162.7500, N'International shipment')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (94, 1, 553, 52.2500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (95, 1, 572, 600.0000, N'Books for research')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (96, 1, 400, 26881.4000, N'MVS JCL')
    GO
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (97, 1, 170, 356.4800, N'Network wiring')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (98, 1, 572, 579.4200, N'Catalog ad')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (99, 1, 553, 59.9700, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (100, 1, 553, 67.9200, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (101, 1, 553, 30.7500, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (102, 1, 400, 20551.1800, N'CICS book printing')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (103, 1, 553, 2051.5900, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (104, 1, 553, 44.4400, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (105, 1, 582, 503.2000, N'Bronco lease')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (106, 1, 400, 23517.5800, N'DB2 book printing')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (107, 1, 553, 3689.9900, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (108, 1, 553, 67.0000, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (109, 1, 403, 1000.4600, N'Crash Course covers')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (110, 1, 540, 90.3600, N'Card deck advertising')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (111, 1, 553, 22.5700, N'Freight')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (112, 1, 400, 10976.0600, N'VSAM book printing')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (113, 1, 510, 224.0000, N'Health Insurance')
    INSERT InvoiceLineItems (InvoiceID, InvoiceSequence, AccountNo, InvoiceLineItemAmount, InvoiceLineItemDescription) VALUES (114, 1, 553, 127.7500, N'Freight')
                

Un join interno con un nome di correlazione che semplifica la query

    USE AP
    GO
    SELECT InvoiceNumber, InvoiceLineitemAmount, InvoiceLineitemDescription
    FROM Invoices JOIN InvoiceLineitems AS Lineitems
       ON Invoices.InvoiceID = Lineitems.InvoiceID
    WHERE AccountNo = 540
    ORDER BY InvoiceDate;
                

Descrizione

Come lavorare con le tabelle di diversi database

Anche se non è frequente, può capitare di dover unire dati provenienti da tabelle che risiedono in database diversi. Per farlo, è necessario qualificare uno o più nomi di tabelle. L'esempio qui sotto mostra come fare. Per cominciare, la figura presenta la sintassi di un nome di oggetto qualificato. Come si può vedere, un nome completamente qualificato è composto da quattro parti: un nome di server, un nome di database, un nome di schema e un nome di tabella. In questa lezione si apprenderà come qualificare i nomi delle tabelle. Tuttavia, è bene sapere che è possibile questa sintassi anche con altri oggetti. La prima istruzione SELECT di questa figura illustra l'uso di nomi di oggetti completamente qualificati. Questa istruzione unisce i dati di due tabelle (Venditori e Clienti) in due database diversi (AP e ProductOrders). Entrambi i database si trovano sullo stesso server (SERVER2025) e sono memorizzati nello stesso schema (dbo ). In questo caso, a entrambe le tabelle sono stati assegnati dei nomi di correlazione per facilitarne il riferimento nella condizione di join. Anche se è possibile qualificare tutti i nomi delle tabelle in questo modo, di solito si specificano solo le parti che sono diverse dalle impostazioni correnti. Quando si avvia Management Studio, ad esempio, ci si connette a un server specifico. Finché si lavora con i database di quel server, non è necessario includere il nome del server. Allo stesso modo, prima di eseguire un'istruzione, si seleziona di solito il database che utilizza. Quindi, finché si lavora con le tabelle di quel database, non è necessario includere il nome del database. Si può anche omettere il nome dello schema, purché si lavori con le tabelle dello schema predefinito dell'utente (vedere lezione 17) o dello schema dbo. Ecco perché tutte le istruzioni viste fino a questo punto hanno incluso solo il nome della tabella. Quando si omettono una o più parti di un nome di oggetto completamente qualificato, si crea un nome di oggetto parzialmente qualificato. Si noti che, poiché il nome dello schema si colloca tra il nome del database e il nome della tabella, sono stati codificati due caratteri punto per indicare che questa parte del nome è stata omessa.

La sintassi di un nome di oggetto completamente qualificato

    linked_server.database.schema.object
                

Creare il database ProductOrders eseguendo in una nuova query il codice SQL contenuto nel file createProductOrders.txt

Un join con nomi di tabelle parzialmente qualificati

    USE AP
    GO
    SELECT VendorName, CustLastName, CustFirstName,
        VendorState AS State, VendorCity AS City
    FROM Vendors
        JOIN ProductOrders..Customers AS Customers
        ON Vendors.VendorZipCode = Customers.CustZip
    ORDER BY State, City
                

Descrizione

Come utilizzare le condizioni di unione composte

Sebbene una condizione di unione sia tipicamente costituita da un singolo confronto, è possibile includere due o più confronti in una condizione di unione utilizzando gli operatori AND e OR. L'esempio qui sotto ne illustra il funzionamento. Nella prima istruzione SELECT di questa figura, si può notare che le fatture e le linee di fattura sono unite in base a due confronti. In primo luogo, lnvoiceID della tabella fatture, viene confrontata con la chiave esterna della tabella lnvoiceLineltems anch'essa denominata lnvoiceID. Come negli esempi precedenti questo confronto utilizza una condizione di uguaglianza. Quindi, la colonna lnvoiceTotal della tabella Fatture viene testata per verificare se il valore è maggiore di quello della tabella lnvoiceLineltemAmount della tabella InvoiceLineltems. Ciò significa che solo le fatture che hanno due o più voci saranno incluse nell'insieme dei risultati. L'esempio mostra una parte dell'insieme dei risultati. Un altro modo per codificare queste condizioni è quello di codificare la condizione di join primario nella clausola FROM e l'altra condizione nella clausola WHERE. Questo è illustrato dalla seconda istruzione SELECT. Quando si codificano condizioni di unione composte separate come questa, la condizione di unione nell'espressione ON viene eseguita prima che le tabelle vengano unite, mentre la condizione di ricerca nella clausola WHERE viene eseguita dopo l'unione delle tabelle. Per questo motivo, ci si potrebbe aspettare che un'istruzione SELECT venga eseguita in modo più efficiente se si codifica la condizione di ricerca nell'espressione ON. Tuttavia, SQL Server esamina le condizioni di unione e di ricerca durante l'ottimizzazione della query. Quindi non è necessario preoccuparsi di quale sia la tecnica più efficiente. È invece necessario codificare le condizioni in modo che siano facilmente comprensibili.

Un join interno con due condizioni. Solo le fatture che hanno due o più voci saranno incluse nell'insieme dei risultati

    USE AP
    GO
    SELECT InvoiceNumber, InvoiceDate,
        InvoiceTotal, InvoiceLineitemAmount
    FROM Invoices JOIN InvoiceLineitems AS Lineitems
        ON (Invoices.InvoiceID = Lineitems.InvoiceID) AND
            (Invoices.InvoiceTotal > Lineitems.InvoiceLineitemAmount )
    ORDER BY InvoiceNumber
                

La stessa unione con la seconda condizione codificata in una clausola WHERE

    USE AP
    GO
    SELECT InvoiceNumber, InvoiceDate,
        InvoiceTotal, InvoiceLineitemAmount
    FROM Invoices JOIN InvoiceLineitems AS Lineitems
        ON Invoices.InvoiceID = Lineitems.InvoiceID
    WHERE Invoices.InvoiceTotal > Lineitems.InvoiceLineitemAmount
    ORDER BY InvoiceNumber
                

Descrizione

Come utilizzare un self join

Una self-join è una join in cui una tabella è unita a se stessa. Sebbene i self join siano rari, ci sono alcune query uniche che si risolvono meglio utilizzando i self-join. L'esempio qui sotto presenta un esempio di self-join che utilizza la tabella Vendors. Si noti che, poiché la stessa tabella viene utilizzata due volte, vengono utilizzati nomi di correlazione per distinguere le due occorrenze della tabella. Inoltre, ogni nome di colonna utilizzato nella query è qualificato dal nome della correlazione, poiché le colonne sono presenti in entrambe le tabelle. La condizione di join in questo esempio utilizza tre confronti. I primi due corrispondono alle colonne VendorCity e VendorState delle due tabelle. Di conseguenza, la query restituirà le righe dei fornitori che risiedono nella stessa città e nello stesso stato di un altro fornitore. Poiché un fornitore risiede nella stessa città e nello stesso stato di se stesso, tuttavia, viene incluso un terzo confronto per escludere le righe che corrispondono a un fornitore con se stesso. A tale scopo, questa condizione utilizza l'operatore not equal per confrontare le colonne VendorID delle due tabelle. Si noti che anche la parola chiave DISTINCT è inclusa in questa istruzione SELECT. In questo modo, un fornitore compare solo una volta nell'insieme dei risultati. Altrimenti comparirebbe una volta per ogni riga con città e stato corrispondenti. Questo esempio mostra anche come sia possibile utilizzare colonne diverse dalle colonne chiave in una condizione di unione. Si tenga presente, tuttavia, che si tratta di una situazione insolita e che non è probabile che si codifichino spesso join di questo tipo.

Un self-join che restituisce i venditori delle città in comune con altri venditori

    USE AP
    GO
    SELECT DISTINCT Vendorsl.VendorName, Vendorsl.VendorCity,
        Vendorsl.VendorState
    FROM Vendors AS Vendorsl JOIN Vendors AS Vendors2
        ON (Vendorsl.VendorCity = Vendors2.VendorCity) AND
            (Vendorsl.VendorState = Vendors2.VendorState) AND
            (Vendorsl.VendorID <> Vendors2.VendorID)
    ORDER BY Vendorsl.VendorState, Vendorsl.VendorCity
                

Descrizione

Join interni che uniscono più di due tabelle

In questa lezione abbiamo visto come unire i dati di due tabelle. Tuttavia, SQL Server consente di unire dati provenienti da un massimo di 256 tabelle. Naturalmente, è probabile che sia mai necessario unire i dati di più di qualche tabella. Inoltre, ogni join richiede risorse di sistema aggiuntive, per cui è consigliabile limitare il numero di tabelle unite quando possibile. L'istruzione SELECT dell'esempio qui sotto unisce i dati di quattro tabelle: Venditori, Fatture, FattureLineltems e GLAccounts. Ogni unione si basa sulla relazione tra la chiave primaria di una tabella e una chiave esterna dell'altra tabella. Ad esempio, la colonna AccountNo è la chiave primaria della tabella GLAccounts e una chiave esterna dell'altra tabella. Sotto l'istruzione SELECT, si possono vedere tre tabelle. La prima presenta il risultato del join tra le tabelle Vendors e Invoices. Questa tabella può essere definita una tabella intermedia perché contiene risultati intermedi. Analogamente, la seconda tabella mostra il risultato dell'unione tra la prima tabella intermedia e la tabella lnvoiceLineltems. La terza tabella mostra il risultato dell'unione tra la seconda tabella intermedia e la tabella GLAccounts dopo l'applicazione della sequenza ORDER BY. Nell'esaminare le tre tabelle in questo esempio, si tenga presente che SQL Server potrebbe non elaborare le unioni come illustrato qui. Tuttavia, l'idea delle tabelle intermedie dovrebbe aiutare a capire come funzionano le giunzioni tra più tabelle.

Creazione della tabella GLAccounts

    USE AP
    GO
    -- create the GLAccounts table
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE GLAccounts (
        AccountNo int NOT NULL,
        AccountDescription varchar(50) NOT NULL,
        CONSTRAINT PK_GLAccounts PRIMARY KEY CLUSTERED 
        (
            AccountNo ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ) 
    GO
                

Inserimento dati nella tabella GLAccounts

    USE AP
    GO
    -- insert the records into GLAccounts table
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (100, N'Cash')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (110, N'Accounts Receivable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (120, N'Book Inventory')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (150, N'Furniture')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (160, N'Computer Equipment')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (162, N'Capitalized Lease')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (167, N'Software')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (170, N'Other Equipment')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (181, N'Book Development')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (200, N'Accounts Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (205, N'Royalties Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (221, N'401K Employee Contributions')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (230, N'Sales Taxes Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (234, N'Medicare Taxes Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (235, N'Income Taxes Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (237, N'State Payroll Taxes Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (238, N'Employee FICA Taxes Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (239, N'Employer FICA Taxes Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (241, N'Employer FUTA Taxes Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (242, N'Employee SDI Taxes Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (243, N'Employer UCI Taxes Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (251, N'IBM Credit Corporation Payable')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (280, N'Capital Stock')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (290, N'Retained Earnings')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (300, N'Retail Sales')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (301, N'College Sales')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (302, N'Trade Sales')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (306, N'Consignment Sales')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (310, N'Compositing Revenue')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (394, N'Book Club Royalties')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (400, N'Book Printing Costs')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (403, N'Book Production Costs')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (500, N'Salaries and Wages')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (505, N'FICA')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (506, N'FUTA')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (507, N'UCI')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (508, N'Medicare')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (510, N'Group Insurance')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (520, N'Building Lease')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (521, N'Utilities')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (522, N'Telephone')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (523, N'Building Maintenance')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (527, N'Computer Equipment Maintenance')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (528, N'IBM Lease')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (532, N'Equipment Rental')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (536, N'Card Deck Advertising')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (540, N'Direct Mail Advertising')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (541, N'Space Advertising')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (546, N'Exhibits and Shows')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (548, N'Web Site Production and Fees')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (550, N'Packaging Materials')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (551, N'Business Forms')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (552, N'Postage')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (553, N'Freight')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (555, N'Collection Agency Fees')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (556, N'Credit Card Handling')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (565, N'Bank Fees')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (568, N'Auto License Fee')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (569, N'Auto Expense')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (570, N'Office Supplies')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (572, N'Books, Dues, and Subscriptions')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (574, N'Business Licenses and Taxes')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (576, N'PC Software')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (580, N'Meals')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (582, N'Travel and Accomodations')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (589, N'Outside Services')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (590, N'Business Insurance')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (591, N'Accounting')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (610, N'Charitable Contributions')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (611, N'Profit Sharing Contributions')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (620, N'Interest Paid to Banks')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (621, N'Other Interest')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (630, N'Federal Corporation Income Taxes')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (631, N'State Corporation Income Taxes')
    INSERT GLAccounts (AccountNo, AccountDescription) VALUES (632, N'Sales Tax')
    GO
                

Un'istruzione SELECT che unisce quattro tabelle

    USE AP
    GO
    SELECT VendorName, InvoiceNumber, InvoiceDate,
        InvoiceLineitemAmount AS LineitemAmount, AccountDescription,
        InvoiceLineitems.AccountNo, GLAccounts.AccountNo
    FROM Vendors
        JOIN Invoices ON Vendors.VendorID = Invoices.VendorID
        JOIN InvoiceLineitems
            ON Invoices.InvoiceID = InvoiceLineitems.InvoiceID
        JOIN GLAccounts ON InvoiceLineitems.AccountNo = GLAccounts.AccountNo
    WHERE (InvoiceTotal - PaymentTotal - CreditTotal) > 0
    ORDER BY VendorName, LineitemAmount DESC
                

Descrizione

Come utilizzare la sintassi di join interno implicito

All'inizio di questa lezione, ho menzionato che SQL Server fornisce una sintassi implicita per l'unione delle tabelle. Questa sintassi era utilizzata prima degli standard SQL-92. Anche se vi consiglio di utilizzare la sintassi esplicita, dovreste conoscere la sintassi implicita nel caso in cui doveste gestire delle istruzioni SQL che la utilizzano. L'esempio qui sotto presenta la sintassi implicita di un join interno e due istruzioni che la utilizzano. Come si può vedere, le tabelle da unire sono semplicemente elencate nella clausola FROM. Quindi, le condizioni di unione sono incluse nella clausola WHERE. La prima istruzione SELECT, ad esempio, unisce i dati delle tabelle Venditori e Fatture. Come l'istruzione SELECT vista in precedenza, queste tabelle sono unite in base al confronto tra le colonne VendorID delle due tabelle. In questo caso, però, il confronto è codificato come condizione di ricerca della clausola WHERE. Se si confronta il set di risultati mostrato in questo esempio con quello precedente, si noterà che sono identici. La seconda istruzione SELECT utilizza la sintassi implicita per unire i dati di quattro tabelle. Si tratta della stessa unione vista nell'esempio precedente. Si noti in questo esempio che le tre condizioni di unione sono combinate nella clausola WHERE con l'operatore AND. Inoltre, viene utilizzato l'operatore AND per combinare le condizioni di join con la condizione di ricerca. Poiché la sintassi esplicita per le unioni consente di separare le condizioni di unione da quelle di ricerca, le istruzioni che utilizzano la sintassi esplicita sono in genere più facili da leggere rispetto a quelle che utilizzano la sintassi implicita. Inoltre, la sintassi esplicita consente di evitare un errore di codifica comune con la sintassi implicita: l'omissione della condizione di unione. Come si apprenderà più avanti in questo capitolo, un join implicito senza una condizione di join dà luogo a un join incrociato, che può restituire un gran numero di righe. Per questi motivi, vi consiglio di utilizzare la sintassi esplicita in tutto il vostro nuovo codice SQL.

La sintassi implicita per un join interno

    SELECT select_list
    FROM table_l, table_2 [, table_3] ...
    WHERE table_l.column_name operator table_2.column_name
        [AND table_2.column_name operator table_3.column_name] ...
                

Un'istruzione SELECT che unisce le tabelle Fornitori e Fatture

    USE AP
    GO
    SELECT InvoiceNumber, VendorName
    FROM Vendors, Invoices
    WHERE Vendors.VendorID = Invoices.VendorID
                

Un'istruzione che unisce quattro tabelle

    USE AP
    GO
    SELECT VendorName, InvoiceNumber, InvoiceDate,
        InvoiceLineitemAmount AS LineitemAmount, AccountDescription
    FROM Vendors, Invoices, InvoiceLineitems, GLAccounts
    WHERE vendors.vendorID = Invoices.vendorID
        AND Invoices.InvoiceID = InvoiceLineitems.InvoiceID
        AND InvoiceLineitems.AccountNo = GLAccounts.AccountNo
        AND (InvoiceTotal - PaymentTotal - CreditTotal) > 0
    ORDER BY VendorName, LineitemAmount DESC
                

Descrizione

Come lavorare con le giunzioni esterne

Sebbene le join interne siano il tipo di join che si usa più spesso, SQL Server supporta anche le join esterne. A differenza di una join interna, una outer join restituisce tutte le righe di una o di entrambe le tabelle coinvolte nel join, indipendentemente dal fatto che la condizione di join sia vera. Il funzionamento di questa funzione è illustrato negli argomenti che seguono.

Come codificare un join esterno

L'esempio qui sotto presenta la sintassi esplicita per la codifica di una join esterna. Poiché questa sintassi è simile alla sintassi esplicita per le giunzioni interne, non dovrebbero esserci problemi a capire come funziona. La differenza principale è che si includono la parola chiave LEFT, RIGHT o FULL per specificare il tipo di join esterno che si desidera eseguire. Come si può vedere nella sintassi, è possibile includere anche la parola chiave OUTER ma è opzionale e di solito viene omessa. La tabella in questo esempio riassume le differenze tra join esterno sinistro, destro e completo. Quando si utilizza una join esterna sinistra, l'insieme dei risultati comprende tutte le righe della prima tabella, o sinistra. Allo stesso modo, quando si utilizza una join esterna destra, l'insieme dei risultati include tutte le righe della seconda tabella, o destra. E quando si utilizza una join esterna completa, l'insieme dei risultati include tutte le righe di entrambe le tabelle. L'esempio illustra una join esterna sinistra. In questo caso, la tabella Venditori è unita alla tabella Fatture. Si noti che l'insieme dei risultati include le righe dei fornitori anche se non vengono trovate fatture corrispondenti. In questo caso, vengono restituiti valori nulli per le colonne della tabella Fatture. Quando si codificano le join esterne, è prassi comune evitare di usare le join destre. A tale scopo, è possibile sostituire una join esterna sinistra con una join esterna destra, invertendo l'ordine delle tabelle nella clausola FROM e utilizzando la parola chiave LEFT al posto di RIGHT. Questo spesso facilita la lettura delle istruzioni che uniscono più di due tabelle. Oltre alla sintassi esplicita per la codifica delle join esterne, le versioni precedenti di SQL Server prevedevano una sintassi implicita. Questa funziona più o meno come la sintassi implicita per la codifica di join interni. Per i join esterni, tuttavia, si utilizzava l'operatore *= nella clausola WHERE per identificare un join esterno sinistro e l'operatore =* per identificare un join esterno destro. Sebbene non sia possibile utilizzare questi operatori da SQL Server 2005 e successivi, è bene conoscerli almeno nel caso in cui si incontrino in query più vecchie.

La sintassi esplicita per un join esterno

    SELECT select_list
    FROM table_l
        {LEFT | RIGHT IFULL} [OUTER] JOIN table_2
            ON join_condition_l
        [{LEFT | RIGHT IFULL} [OUTER] JOIN table_3
    ON join_condition_2] ...
                

Cosa fanno i join esterni

join esterni
Tipo di joinMantenere le righe non corrispondenti da
Left outer joinLa prima tabella (a sinistra)
Right outer joinla seconda tabella (a destra)
Full outer joinEntrambe le tabelle

Un'istruzione SELECT che utilizza un join esterno sinistro

    USE AP
    GO
    SELECT VendorName, InvoiceNumber, InvoiceTotal
    FROM Vendors LEFT JOIN Invoices
        ON Vendors.VendorID = Invoices.VendorID
    ORDER BY VendorName
                

Descrizione

Esempi di join esterni

Per comprendere meglio il funzionamento dei join esterni, l'esempio qui sotto presenta altri tre esempi. Questi esempi utilizzano le tabelle Reparti e Dipendenti mostrate nella parte superiore dell'esempio. In ogni caso, la condizione di join unisce le tabelle in base ai valori delle colonne DeptNo. La prima istruzione SELECT esegue una join esterna sinistra su queste due tabelle. Nel risultato prodotto da questa istruzione, si può notare che il dipartimento numero 3 è incluso nel set di risultati anche se nessuno dei dipendenti della tabella Employees lavora in quel reparto. Per questo motivo, viene assegnato un valore nullo alla colonna LastName di quella tabella. La seconda istruzione SELECT utilizza un join esterno destro. In questo caso, tutte le righe della tabella Employees sono incluse nell'insieme dei risultati. Si noti, tuttavia, che due dei dipendenti, Watson e Locario, sono assegnati a un reparto che non esiste nella tabella Departments. Naturalmente, se la colonna DeptNo della tabella fosse stata definita come chiave esterna alla tabella Reparti, ciò non sarebbe stato possibile. In questo caso, però, non è stata definita una chiave esterna, quindi vengono restituiti valori nulli per la colonna DeptName in queste due righe. La terza istruzione SELECT di questa figura illustra una join esterna completa. Se si confrontano i risultati di questa query con quelli delle query che utilizzano un join esterno sinistro e destro, si noterà che si tratta di una combinazione dei due join. In altre parole, ogni riga della tabella Reparti è inclusa nel set di risultati, insieme a ogni riga della tabella Dipendenti. Poiché la colonna DeptNo è in entrambe le tabelle, è possibile identificare chiaramente la riga della tabella Departments che non ha una riga corrispondente nella tabella Dipendenti e le due righe della tabella Dipendenti che non hanno una riga corrispondente nella tabella Reparti.

Creazione della tabella Departments

    USE AP
    GO
    -- create the Departments table
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE Departments (
        DeptNo int IDENTITY(1,1) NOT NULL,
        DeptName varchar(50) NOT NULL,
        CONSTRAINT PK_Departments PRIMARY KEY CLUSTERED 
        (
            DeptNo ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    )
    GO
                

Creazione della tabella Employees

    USE AP
    GO
    -- create the Employees table
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE Employees (
        EmployeeID int IDENTITY(1,1) NOT NULL,
        LastName varchar(35) NOT NULL,
        FirstName varchar(35) NOT NULL,
        DeptNo int NOT NULL,
        ManagerID int NULL,
        CONSTRAINT PK_Employees PRIMARY KEY CLUSTERED 
        (
            EmployeeID ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ) 
    GO
                

Inserisco Departments

    USE AP
    GO
    SET IDENTITY_INSERT Departments ON 
    INSERT Departments (DeptNo, DeptName) VALUES (1, N'Accounting')
    INSERT Departments (DeptNo, DeptName) VALUES (2, N'Payroll')
    INSERT Departments (DeptNo, DeptName) VALUES (3, N'Operations')
    INSERT Departments (DeptNo, DeptName) VALUES (4, N'Personnel')
    INSERT Departments (DeptNo, DeptName) VALUES (5, N'Maintenance')
    SET IDENTITY_INSERT Departments OFF
                

Inserisco Employees

    USE AP
    GO
    SET IDENTITY_INSERT Employees ON 
    INSERT Employees (EmployeeID, LastName, FirstName, DeptNo, ManagerID) VALUES (1, N'Smith', N'Cindy', 2, NULL)
    INSERT Employees (EmployeeID, LastName, FirstName, DeptNo, ManagerID) VALUES (2, N'Jones', N'Elmer', 4, 1)
    INSERT Employees (EmployeeID, LastName, FirstName, DeptNo, ManagerID) VALUES (3, N'Simonian', N'Ralph', 2, 2)
    INSERT Employees (EmployeeID, LastName, FirstName, DeptNo, ManagerID) VALUES (4, N'Hernandez', N'Olivia', 1, 2)
    INSERT Employees (EmployeeID, LastName, FirstName, DeptNo, ManagerID) VALUES (5, N'Aaronsen', N'Robert', 2, 3)
    INSERT Employees (EmployeeID, LastName, FirstName, DeptNo, ManagerID) VALUES (6, N'Watson', N'Denise', 6, 3)
    INSERT Employees (EmployeeID, LastName, FirstName, DeptNo, ManagerID) VALUES (7, N'Hardy', N'Thomas', 5, 2)
    INSERT Employees (EmployeeID, LastName, FirstName, DeptNo, ManagerID) VALUES (8, N'O''Leary', N'Rhea', 4, 2)
    INSERT Employees (EmployeeID, LastName, FirstName, DeptNo, ManagerID) VALUES (9, N'Locario', N'Paulo', 6, 1)
    SET IDENTITY_INSERT Employees OFF
                

Un join esterno sinistro

    USE AP
    GO
    SELECT Departments.DeptName, Departments.DeptNo, Employees.LastName
    FROM Departments LEFT JOIN Employees
        ON Departments.DeptNo = Employees.DeptNo
                

Un join esterno destro

    USE AP
    GO
    SELECT Departments.DeptName, Departments.DeptNo, Employees.LastName
    FROM Departments RIGHT JOIN Employees
        ON Departments.DeptNo = Employees.DeptNo
                

    USE AP
    GO
    SELECT Departments.DeptName, Departments.DeptNo, Employees.LastName
    FROM Departments FULL JOIN Employees
        ON Departments.DeptNo = Employees.DeptNo
                

Descrizione

Outer join che uniscono più di due tabelle

Come con i Join interni, è possibile utilizzare i Join esterni per unire i dati di più di due tabelle. I due esempi qui sotto ne illustrano il funzionamento. Questi esempi utilizzano le tabelle Reparti e Dipendenti viste nell'esempio precedente, oltre a una tabella Progetti. Il primo esempio utilizza Join esterni a sinistra per unire i dati delle tre tabelle. Anche in questo caso si può notare che nessuno dei dipendenti della tabella Employees è assegnato al reparto Operations. Per questo motivo, vengono restituiti valori per le colonne delle tabelle Dipendenti e Progetti. Inoltre, si può notare che due dipendenti, Hardy e Jones, non sono assegnati a un progetto. Il secondo esempio in questa figura utilizza Join esterni completi per unire le tre tabelle. Questo set di risultati include le righe non abbinate delle tabelle Reparti e Dipendenti, proprio come il set di risultati visto in precedenza. Proprio come l'insieme di risultati visto in precedenza è stato creato con un join esterno completo. Inoltre, l'insieme di risultati di questo esempio include una riga dalla tabella Progetti: quella relativa al progetto numero P1014. In altre parole, nessuno dei dipendenti è assegnato a questo progetto.

Creazione della tabella Projects

    USE AP
    GO
    -- create the Projects table
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE Projects (
        ProjectID int IDENTITY(1,1) NOT NULL,
        ProjectNo char(5) NOT NULL,
        EmployeeID int NOT NULL,
        CONSTRAINT PK_Projects PRIMARY KEY CLUSTERED 
        (
            ProjectID ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)        
    )
    GO
                

Inserimento Projects

    USE AP
    GO
    SET IDENTITY_INSERT Projects ON     
    INSERT Projects (ProjectID, ProjectNo, EmployeeID) VALUES (1, N'P1011', 8)
    INSERT Projects (ProjectID, ProjectNo, EmployeeID) VALUES (2, N'P1011', 4)
    INSERT Projects (ProjectID, ProjectNo, EmployeeID) VALUES (3, N'P1012', 3)
    INSERT Projects (ProjectID, ProjectNo, EmployeeID) VALUES (4, N'P1012', 1)
    INSERT Projects (ProjectID, ProjectNo, EmployeeID) VALUES (5, N'P1012', 5)
    INSERT Projects (ProjectID, ProjectNo, EmployeeID) VALUES (6, N'P1013', 6)
    INSERT Projects (ProjectID, ProjectNo, EmployeeID) VALUES (7, N'P1013', 9)
    INSERT Projects (ProjectID, ProjectNo, EmployeeID) VALUES (8, N'P1014', 10)
    SET IDENTITY_INSERT Projects OFF
                

Un'istruzione SELECT che unisce le tre tabelle utilizzando join esterni a sinistra

    USE AP
    GO
    SELECT DeptName, LastName, ProjectNo
    FROM Departments
        LEFT JOIN Employees
            ON Departments.DeptNo = Employees.DeptNo
        LEFT JOIN Projects
            ON Employees.EmployeeID = Projects.EmployeeID
    ORDER BY DeptName, LastName, ProjectNo
                

Un'istruzione SELECT che unisce le tre tabelle utilizzando join esterni completi

    USE AP
    GO
    SELECT DeptName, LastName, ProjectNo
    FROM Departments
        FULL JOIN Employees
            ON Departments.DeptNo - Employees.DeptNo
        FULL JOIN Projects
            ON Employees.EmployeeID = Projects.EmployeeID
    ORDER BY DeptName
                

Altre competenze per lavorare con le unioni

I due argomenti che seguono presentano due abilità aggiuntive per lavorare con i join. Nel primo argomento, imparerete a utilizzare i join interni ed esterni nella stessa istruzione. Poi, nel secondo argomento, imparerete a usare un altro tipo di join, chiamato join incrociato.

Come combinare join interni ed esterni

L'esempio che segue mostra come è possibile combinare join interni ed esterni. In questo esempio, la tabella Reparti viene unita alla tabella Dipendenti utilizzando un join interno. Il risultato è una tabella intermedia che include i reparti con uno o più dipendenti. Si noti che la colonna EmployeeID è mostrata in questa tabella, anche se non è inclusa nell'insieme dei risultati finali. Questo perché viene utilizzata dalla join che segue. Dopo aver unito le tabelle Reparti e Dipendenti, la tabella provvisoria viene unita alla tabella Progetti con un join esterno sinistro. Il risultato è una tabella che include tutti i dipartimenti a cui sono assegnati dipendenti, tutti i dipendenti assegnati a tali dipartimenti e tutti i progetti. Qui si vede chiaramente che a due dipendenti, Hardy e Jones, non sono stati assegnati progetti.

Un'istruzione SELECT che combina un join esterno e uno interno

    USE AP
    GO
    SELECT DeptName, LastName, ProjectNo
    FROM Departments
        JOIN Employees
            ON Departments.DeptNo = Employees.DeptNo
        LEFT JOIN Projects
            ON Employees.EmployeeID = Projects.EmployeeID
    ORDER BY DeptName
                

Descrizione

Come utilizzare i join incrociati

Un join incrociato produce un set di risultati che include ogni riga della prima tabella unita a ogni riga della seconda tabella. L'insieme dei risultati è noto come prodotto cartesiano delle tabelle. L'esempio qui sotto mostra come codificare un join incrociato utilizzando la sintassi esplicita o implicita. Per utilizzare la sintassi esplicita, si includono le parole chiave CROSS JOIN tra le due tabelle nella clausola FROM. Si noti che, per il modo in cui funziona un join, non è necessario includere una condizione di unione. Lo stesso vale quando si usa la sintassi implicita. In questo caso, si elencano semplicemente le tabelle nella clausola FROM e si omette la condizione di join dalla clausola WHERE. Le due istruzioni SELECT di questo esempio illustrano il funzionamento dei cross join. Entrambe le istruzioni combinano i dati delle tabelle Reparti e Dipendenti. Come si può vedere, il risultato è una tabella che include 45 righe. Ognuna delle cinque righe della tabella Reparti combinate con le nove righe della tabella Dipendenti. Anche se questo insieme di risultati è relativamente piccolo, si può immaginare quanto sarebbe grande se le tabelle includessero centinaia o migliaia di righe. Studiando questi esempi, ci si rende conto che i cross join hanno pochi usi pratici. Di conseguenza, raramente, se non mai, sarà necessario utilizzarne uno.

Come codificare un join incrociato utilizzando la sintassi esplicita

La sintassi esplicita di un join incrociato

    SELECT select_list
    FROM table_l CROSS JOIN table_2
                

Un join incrociato che utilizza la sintassi esplicita

    USE AP
    GO
    SELECT Departments.DeptNo, DeptName, EmployeeID, LastName
    FROM Departments CROSS JOIN Employees
    ORDER BY Departments.DeptNo
                

Come codificare un join incrociato utilizzando la sintassi implicita

La sintassi implicita di un join incrociato

    SELECT select_list
    FROM table_l, table_2
                

Un join incrociato che utilizza la sintassi implicita

    USE AP
    GO                    
    SELECT Departments.DeptNo, DeptName, EmployeeID, LastName
    FROM Departments, Employees
    ORDER BY Departments.DeptNo
                

Descrizione

Come lavorare con le unioni in sql

Come un join, una union combina i dati di due o più tabelle. Tuttavia, invece di combinare le colonne delle tabelle di base, un'unione combina le righe di due o più insiemi di risultati. Vedrete come funziona negli argomenti che seguono.

La sintassi di un'unione

L'esempio qui sotto mostra come codificare un'unione. Come mostra la sintassi, si crea un'unione collegando due o più istruzioni SELECT con la parola chiave UNION. Perché funzioni, il risultato di ogni istruzione SELECT deve avere lo stesso numero di colonne e i tipi di dati delle colonne corrispondenti in ogni tabella devono essere compatibili. In questa sintassi, ho indentato tutte le istruzioni SELECT collegate dall'operatore UNION, in modo da rendere più semplice l'operazione. Tuttavia, in un ambiente di produzione, è comune vedere le istruzioni SELECT e l'operatore UNION codificati allo stesso livello di indentazione. Se si vuole ordinare il risultato di un'operazione di unione, si può codificare una clausola ORDER BY dopo l'ultima istruzione SELECT. Si noti che i nomi delle colonne in questa clausola devono essere gli stessi utilizzati nella prima istruzione SELECT. Questo perché i nomi delle colonne usati nella prima istruzione SELECT sono quelli usati nell'insieme dei risultati. Per impostazione predefinita, un'operazione di unione rimuove le righe duplicate dall'insieme dei risultati. Se non si vuole questo, si può includere la parola chiave ALL. Nella maggior parte dei casi, tuttavia, si omette questa parola chiave.

Unioni che combinano dati provenienti da tabelle diverse

L'esempio seguente mostra come utilizzare un'unione per combinare i dati di due tabelle diverse. In questo caso, la tabella Activelnvoices (Fatture attive) contiene le fatture con fatture con saldi in sospeso, mentre la tabella Fatture pagate contiene le fatture che sono state pagate completamente. Entrambe le tabelle hanno la stessa struttura della tabella Fatture, come si è visto nelle figure precedenti. Questa operazione di unione combina le righe di entrambe le tabelle che hanno una data fattura uguale o successiva al 2/1/2016. Si noti che la prima istruzione SELECT include una colonna denominata Sorgente che contiene il valore letterale “Attivo”. La seconda SELECT include una colonna con lo stesso nome, ma che contiene il valore letterale “Pagato”. Questa colonna viene utilizzata per indicare da quale tabella proviene ogni riga del set di risultati. Sebbene a questa colonna sia stato assegnato lo stesso nome in entrambe le istruzioni SELECT è bene sapere che non è detto che sia così. Infatti, nessuna delle colonne deve avere lo stesso nome. Le colonne corrispondenti devono avere tipi di dati compatibili. Ma le relazioni corrispondenti sono determinate dall'ordine in cui le colonne sono codificate nelle clausole SELECT, non dai loro nomi. Quando si usano gli alias di colonna, però, di solito si assegna lo stesso nome alle colonne corrispondenti, in modo che l'istruzione sia più facile da capire.

La sintassi di un'operazione di unione

        SELECT_statement_l
    UNION [ALL]
        SELECT_statement_2
    [UNION [ALL]
        SELECT_statement_3] ...
    [ORDER BY order_by_list]
                

Creare la tabella Activeinvoices

    USE AP
    GO                    
    -- create the ActiveInvoices table
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE ActiveInvoices(
        InvoiceID int IDENTITY(1,1) NOT NULL,
        VendorID int NOT NULL,
        InvoiceNumber varchar(50) NOT NULL,
        InvoiceDate date NOT NULL,
        InvoiceTotal money NOT NULL,
        PaymentTotal money NOT NULL,
        CreditTotal money NOT NULL,
        TermsID int NOT NULL,
        InvoiceDueDate date NOT NULL,
        PaymentDate date NULL,
        CONSTRAINT PK_ActiveInvoices PRIMARY KEY CLUSTERED 
        (
            InvoiceID ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    ) 
    GO
                

Inserire le righe nella tabella Activeinvoices

    USE AP
    GO
    SET IDENTITY_INSERT ActiveInvoices ON 
    INSERT ActiveInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (89, 72, N'39104', CAST(N'2023-01-10' AS Date), 85.3100, 0.0000, 0.0000, 3, CAST(N'2023-02-09' AS Date), NULL)
    INSERT ActiveInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (94, 123, N'963253264', CAST(N'2023-01-18' AS Date), 52.2500, 0.0000, 0.0000, 3, CAST(N'2023-02-17' AS Date), NULL)
    INSERT ActiveInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (98, 83, N'31361833', CAST(N'2023-01-21' AS Date), 579.4200, 0.0000, 0.0000, 2, CAST(N'2023-02-10' AS Date), NULL)
    INSERT ActiveInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (99, 123, N'263253268', CAST(N'2023-01-21' AS Date), 59.9700, 0.0000, 0.0000, 3, CAST(N'2023-02-20' AS Date), NULL)
    INSERT ActiveInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (100, 123, N'263253270', CAST(N'2023-01-22' AS Date), 67.9200, 0.0000, 0.0000, 3, CAST(N'2023-02-21' AS Date), NULL)
    INSERT ActiveInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (101, 123, N'263253273', CAST(N'2023-01-22' AS Date), 30.7500, 0.0000, 0.0000, 3, CAST(N'2023-02-21' AS Date), NULL)
    INSERT ActiveInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (102, 110, N'P-0608', CAST(N'2023-01-23' AS Date), 20551.1800, 0.0000, 1200.0000, 3, CAST(N'2023-02-22' AS Date), NULL)
    INSERT ActiveInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (105, 106, N'9982771', CAST(N'2023-01-24' AS Date), 503.2000, 0.0000, 0.0000, 3, CAST(N'2023-02-23' AS Date), NULL)
    INSERT ActiveInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (110, 80, N'134116', CAST(N'2023-01-28' AS Date), 90.3600, 0.0000, 0.0000, 2, CAST(N'2023-02-17' AS Date), NULL)
    INSERT ActiveInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (112, 110, N'0-2436', CAST(N'2023-01-31' AS Date), 10976.0600, 0.0000, 0.0000, 3, CAST(N'2023-03-01' AS Date), NULL)
    INSERT ActiveInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (113, 37, N'547480102', CAST(N'2023-02-01' AS Date), 224.0000, 0.0000, 0.0000, 3, CAST(N'2023-03-01' AS Date), NULL)
    SET IDENTITY_INSERT ActiveInvoices OFF
                

Creare la tabella PaidInvoices

    USE AP
    GO                    
    -- create the PaidInvoices table
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE PaidInvoices (
        InvoiceID int IDENTITY(1,1) NOT NULL,
        VendorID int NOT NULL,
        InvoiceNumber varchar(50) NOT NULL,
        InvoiceDate date NOT NULL,
        InvoiceTotal money NOT NULL,
        PaymentTotal money NOT NULL,
        CreditTotal money NOT NULL,
        TermsID int NOT NULL,
        InvoiceDueDate date NOT NULL,
        PaymentDate date NULL
        CONSTRAINT PK_PaidInvoices PRIMARY KEY CLUSTERED 
        (
            InvoiceID ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    )
    GO
                

Inserire le righe nella tabella PaidInvoices

    USE AP
    GO
    SET IDENTITY_INSERT PaidInvoices ON
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (1, 122, N'989319-457', CAST(N'2022-10-08' AS Date), 3813.3300, 3813.3300, 0.0000, 3, CAST(N'2022-11-08' AS Date), CAST(N'2022-11-07' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (2, 123, N'263253241', CAST(N'2022-10-10' AS Date), 40.2000, 40.2000, 0.0000, 3, CAST(N'2022-11-10' AS Date), CAST(N'2022-11-14' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (3, 123, N'963253234', CAST(N'2022-10-13' AS Date), 138.7500, 138.7500, 0.0000, 3, CAST(N'2022-11-13' AS Date), CAST(N'2022-11-09' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (4, 123, N'2-000-2993', CAST(N'2022-10-16' AS Date), 144.7000, 144.7000, 0.0000, 3, CAST(N'2022-11-16' AS Date), CAST(N'2022-11-12' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (5, 123, N'963253251', CAST(N'2022-10-16' AS Date), 15.5000, 15.5000, 0.0000, 3, CAST(N'2022-11-16' AS Date), CAST(N'2022-11-11' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (6, 123, N'963253261', CAST(N'2022-10-16' AS Date), 42.7500, 42.7500, 0.0000, 3, CAST(N'2022-11-16' AS Date), CAST(N'2022-11-21' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (7, 123, N'963253237', CAST(N'2022-10-21' AS Date), 172.5000, 172.5000, 0.0000, 3, CAST(N'2022-11-21' AS Date), CAST(N'2022-11-22' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (8, 89, N'125520-1', CAST(N'2022-10-24' AS Date), 95.0000, 95.0000, 0.0000, 1, CAST(N'2022-11-04' AS Date), CAST(N'2022-11-01' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (9, 121, N'97/488', CAST(N'2022-10-24' AS Date), 601.9500, 601.9500, 0.0000, 3, CAST(N'2022-11-24' AS Date), CAST(N'2022-11-21' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (10, 123, N'263253250', CAST(N'2022-10-24' AS Date), 42.6700, 42.6700, 0.0000, 3, CAST(N'2022-11-24' AS Date), CAST(N'2022-11-22' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (11, 123, N'963253262', CAST(N'2022-10-25' AS Date), 42.5000, 42.5000, 0.0000, 3, CAST(N'2022-11-25' AS Date), CAST(N'2022-11-20' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (12, 96, N'I77271-O01', CAST(N'2022-10-26' AS Date), 662.0000, 662.0000, 0.0000, 2, CAST(N'2022-11-16' AS Date), CAST(N'2022-11-13' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (13, 95, N'111-92R-10096', CAST(N'2022-10-30' AS Date), 16.3300, 16.3300, 0.0000, 2, CAST(N'2022-11-20' AS Date), CAST(N'2022-11-23' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (14, 115, N'25022117', CAST(N'2022-11-01' AS Date), 6.0000, 6.0000, 0.0000, 4, CAST(N'2022-12-10' AS Date), CAST(N'2022-12-10' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (15, 48, N'P02-88D77S7', CAST(N'2022-11-03' AS Date), 856.9200, 856.9200, 0.0000, 3, CAST(N'2022-12-02' AS Date), CAST(N'2022-11-30' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (16, 97, N'21-4748363', CAST(N'2022-11-03' AS Date), 9.9500, 9.9500, 0.0000, 2, CAST(N'2022-11-23' AS Date), CAST(N'2022-11-22' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (17, 123, N'4-321-2596', CAST(N'2022-11-05' AS Date), 10.0000, 10.0000, 0.0000, 3, CAST(N'2022-12-04' AS Date), CAST(N'2022-12-05' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (18, 123, N'963253242', CAST(N'2022-11-06' AS Date), 104.0000, 104.0000, 0.0000, 3, CAST(N'2022-12-05' AS Date), CAST(N'2022-12-05' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (19, 34, N'QP58872', CAST(N'2022-11-07' AS Date), 116.5400, 116.5400, 0.0000, 1, CAST(N'2022-11-17' AS Date), CAST(N'2022-11-19' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (20, 115, N'24863706', CAST(N'2022-11-10' AS Date), 6.0000, 6.0000, 0.0000, 4, CAST(N'2022-12-19' AS Date), CAST(N'2022-12-15' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (21, 119, N'10843', CAST(N'2022-11-11' AS Date), 4901.2600, 4901.2600, 0.0000, 2, CAST(N'2022-11-30' AS Date), CAST(N'2022-11-29' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (22, 123, N'963253235', CAST(N'2022-11-11' AS Date), 108.2500, 108.2500, 0.0000, 3, CAST(N'2022-12-10' AS Date), CAST(N'2022-12-09' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (23, 97, N'21-4923721', CAST(N'2022-11-13' AS Date), 9.9500, 9.9500, 0.0000, 2, CAST(N'2022-12-02' AS Date), CAST(N'2022-11-28' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (24, 113, N'77290', CAST(N'2022-11-13' AS Date), 1750.0000, 1750.0000, 0.0000, 5, CAST(N'2023-01-02' AS Date), CAST(N'2023-01-05' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (25, 123, N'963253246', CAST(N'2022-11-13' AS Date), 129.0000, 129.0000, 0.0000, 3, CAST(N'2022-12-12' AS Date), CAST(N'2022-12-09' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (26, 123, N'4-342-8069', CAST(N'2022-11-14' AS Date), 10.0000, 10.0000, 0.0000, 3, CAST(N'2022-12-13' AS Date), CAST(N'2022-12-13' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (27, 88, N'972110', CAST(N'2022-11-15' AS Date), 207.7800, 207.7800, 0.0000, 1, CAST(N'2022-11-25' AS Date), CAST(N'2022-11-27' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (28, 123, N'963253263', CAST(N'2022-11-16' AS Date), 109.5000, 109.5000, 0.0000, 3, CAST(N'2022-12-15' AS Date), CAST(N'2022-12-10' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (29, 108, N'121897', CAST(N'2022-11-19' AS Date), 450.0000, 450.0000, 0.0000, 4, CAST(N'2022-12-28' AS Date), CAST(N'2023-01-03' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (30, 123, N'1-200-5164', CAST(N'2022-11-20' AS Date), 63.4000, 63.4000, 0.0000, 3, CAST(N'2022-12-19' AS Date), CAST(N'2022-12-24' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (31, 104, N'P02-3772', CAST(N'2022-11-21' AS Date), 7125.3400, 7125.3400, 0.0000, 3, CAST(N'2022-12-20' AS Date), CAST(N'2022-12-24' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (32, 121, N'97/486', CAST(N'2022-11-21' AS Date), 953.1000, 953.1000, 0.0000, 3, CAST(N'2022-12-20' AS Date), CAST(N'2022-12-22' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (33, 105, N'94007005', CAST(N'2022-11-23' AS Date), 220.0000, 220.0000, 0.0000, 3, CAST(N'2022-12-22' AS Date), CAST(N'2022-12-26' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (34, 123, N'963253232', CAST(N'2022-11-23' AS Date), 127.7500, 127.7500, 0.0000, 3, CAST(N'2022-12-22' AS Date), CAST(N'2022-12-18' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (35, 107, N'RTR-72-3662-X', CAST(N'2022-11-25' AS Date), 1600.0000, 1600.0000, 0.0000, 4, CAST(N'2023-01-04' AS Date), CAST(N'2023-01-09' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (36, 121, N'97/465', CAST(N'2022-11-25' AS Date), 565.1500, 565.1500, 0.0000, 3, CAST(N'2022-12-24' AS Date), CAST(N'2022-12-24' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (37, 123, N'963253260', CAST(N'2022-11-25' AS Date), 36.0000, 36.0000, 0.0000, 3, CAST(N'2022-12-24' AS Date), CAST(N'2022-12-26' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (38, 123, N'963253272', CAST(N'2022-11-26' AS Date), 61.5000, 61.5000, 0.0000, 3, CAST(N'2022-12-25' AS Date), CAST(N'2022-12-28' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (39, 110, N'0-2058', CAST(N'2022-11-28' AS Date), 37966.1900, 37966.1900, 0.0000, 3, CAST(N'2022-12-27' AS Date), CAST(N'2022-12-28' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (40, 121, N'97/503', CAST(N'2022-11-30' AS Date), 639.7700, 639.7700, 0.0000, 3, CAST(N'2022-12-28' AS Date), CAST(N'2022-12-25' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (41, 123, N'963253255', CAST(N'2022-11-30' AS Date), 53.7500, 53.7500, 0.0000, 3, CAST(N'2022-12-28' AS Date), CAST(N'2022-12-27' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (42, 123, N'94007069', CAST(N'2022-11-30' AS Date), 400.0000, 400.0000, 0.0000, 3, CAST(N'2022-12-28' AS Date), CAST(N'2023-01-01' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (43, 72, N'40318', CAST(N'2022-12-01' AS Date), 21842.0000, 21842.0000, 0.0000, 3, CAST(N'2023-01-01' AS Date), CAST(N'2022-12-28' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (44, 95, N'111-92R-10094', CAST(N'2022-12-01' AS Date), 19.6700, 19.6700, 0.0000, 2, CAST(N'2022-12-21' AS Date), CAST(N'2022-12-24' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (45, 122, N'989319-437', CAST(N'2022-12-01' AS Date), 2765.3600, 2765.3600, 0.0000, 3, CAST(N'2023-01-01' AS Date), CAST(N'2022-12-28' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (46, 37, N'547481328', CAST(N'2022-12-03' AS Date), 224.0000, 224.0000, 0.0000, 3, CAST(N'2023-01-03' AS Date), CAST(N'2023-01-04' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (47, 83, N'31359783', CAST(N'2022-12-03' AS Date), 1575.0000, 1575.0000, 0.0000, 2, CAST(N'2022-12-23' AS Date), CAST(N'2022-12-21' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (48, 123, N'1-202-2978', CAST(N'2022-12-03' AS Date), 33.0000, 33.0000, 0.0000, 3, CAST(N'2023-01-03' AS Date), CAST(N'2023-01-05' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (49, 95, N'111-92R-10097', CAST(N'2022-12-04' AS Date), 16.3300, 16.3300, 0.0000, 2, CAST(N'2022-12-24' AS Date), CAST(N'2022-12-26' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (50, 37, N'547479217', CAST(N'2022-12-07' AS Date), 116.0000, 116.0000, 0.0000, 3, CAST(N'2023-01-07' AS Date), CAST(N'2023-01-07' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (51, 122, N'989319-477', CAST(N'2022-12-08' AS Date), 2184.1100, 2184.1100, 0.0000, 3, CAST(N'2023-01-08' AS Date), CAST(N'2023-01-08' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (52, 34, N'Q545443', CAST(N'2022-12-09' AS Date), 1083.5800, 1083.5800, 0.0000, 1, CAST(N'2022-12-19' AS Date), CAST(N'2022-12-23' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (53, 95, N'111-92R-10092', CAST(N'2022-12-09' AS Date), 46.2100, 46.2100, 0.0000, 2, CAST(N'2022-12-28' AS Date), CAST(N'2023-01-02' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (54, 121, N'97/553B', CAST(N'2022-12-10' AS Date), 313.5500, 313.5500, 0.0000, 3, CAST(N'2023-01-10' AS Date), CAST(N'2023-01-09' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (55, 123, N'963253245', CAST(N'2022-12-10' AS Date), 40.7500, 40.7500, 0.0000, 3, CAST(N'2023-01-10' AS Date), CAST(N'2023-01-12' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (56, 86, N'367447', CAST(N'2022-12-11' AS Date), 2433.0000, 2433.0000, 0.0000, 1, CAST(N'2022-12-21' AS Date), CAST(N'2022-12-17' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (57, 103, N'75C-90227', CAST(N'2022-12-11' AS Date), 1367.5000, 1367.5000, 0.0000, 5, CAST(N'2023-01-31' AS Date), CAST(N'2023-01-31' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (58, 123, N'963253256', CAST(N'2022-12-11' AS Date), 53.2500, 53.2500, 0.0000, 3, CAST(N'2023-01-11' AS Date), CAST(N'2023-01-07' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (59, 123, N'4-314-3057', CAST(N'2022-12-11' AS Date), 13.7500, 13.7500, 0.0000, 3, CAST(N'2023-01-11' AS Date), CAST(N'2023-01-15' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (60, 122, N'989319-497', CAST(N'2022-12-12' AS Date), 2312.2000, 2312.2000, 0.0000, 3, CAST(N'2023-01-12' AS Date), CAST(N'2023-01-09' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (61, 115, N'24946731', CAST(N'2022-12-15' AS Date), 25.6700, 25.6700, 0.0000, 4, CAST(N'2023-01-25' AS Date), CAST(N'2023-01-26' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (62, 123, N'963253269', CAST(N'2022-12-15' AS Date), 26.7500, 26.7500, 0.0000, 3, CAST(N'2023-01-15' AS Date), CAST(N'2023-01-11' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (63, 122, N'989319-427', CAST(N'2022-12-16' AS Date), 2115.8100, 2115.8100, 0.0000, 3, CAST(N'2023-01-16' AS Date), CAST(N'2023-01-19' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (64, 123, N'963253267', CAST(N'2022-12-17' AS Date), 23.5000, 23.5000, 0.0000, 3, CAST(N'2023-01-17' AS Date), CAST(N'2023-01-19' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (65, 99, N'509786', CAST(N'2022-12-18' AS Date), 6940.2500, 6940.2500, 0.0000, 3, CAST(N'2023-01-18' AS Date), CAST(N'2023-01-15' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (66, 123, N'263253253', CAST(N'2022-12-18' AS Date), 31.9500, 31.9500, 0.0000, 3, CAST(N'2023-01-18' AS Date), CAST(N'2023-01-21' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (67, 122, N'989319-487', CAST(N'2022-12-20' AS Date), 1927.5400, 1927.5400, 0.0000, 3, CAST(N'2023-01-20' AS Date), CAST(N'2023-01-18' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (68, 81, N'MABO1489', CAST(N'2022-12-21' AS Date), 936.9300, 936.9300, 0.0000, 2, CAST(N'2023-01-11' AS Date), CAST(N'2023-01-10' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (69, 80, N'133560', CAST(N'2022-12-22' AS Date), 175.0000, 175.0000, 0.0000, 2, CAST(N'2023-01-12' AS Date), CAST(N'2023-01-16' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (70, 115, N'24780512', CAST(N'2022-12-22' AS Date), 6.0000, 6.0000, 0.0000, 4, CAST(N'2023-02-01' AS Date), CAST(N'2023-01-29' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (71, 123, N'963253254', CAST(N'2022-12-22' AS Date), 108.5000, 108.5000, 0.0000, 3, CAST(N'2023-01-22' AS Date), CAST(N'2023-01-20' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (72, 123, N'43966316', CAST(N'2022-12-22' AS Date), 10.0000, 10.0000, 0.0000, 3, CAST(N'2023-01-22' AS Date), CAST(N'2023-01-17' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (73, 114, N'CBM9920-M-T77109', CAST(N'2022-12-23' AS Date), 290.0000, 290.0000, 0.0000, 1, CAST(N'2023-01-03' AS Date), CAST(N'2022-12-28' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (74, 102, N'109596', CAST(N'2022-12-24' AS Date), 41.8000, 41.8000, 0.0000, 4, CAST(N'2023-02-03' AS Date), CAST(N'2023-02-04' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (75, 123, N'7548906-20', CAST(N'2022-12-24' AS Date), 27.0000, 27.0000, 0.0000, 3, CAST(N'2023-01-24' AS Date), CAST(N'2023-01-24' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (76, 123, N'963253248', CAST(N'2022-12-24' AS Date), 241.0000, 241.0000, 0.0000, 3, CAST(N'2023-01-24' AS Date), CAST(N'2023-01-25' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (77, 121, N'97/553', CAST(N'2022-12-25' AS Date), 904.1400, 904.1400, 0.0000, 3, CAST(N'2023-01-25' AS Date), CAST(N'2023-01-25' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (78, 121, N'97/522', CAST(N'2022-12-28' AS Date), 1962.1300, 1762.1300, 200.0000, 3, CAST(N'2023-01-28' AS Date), CAST(N'2023-01-30' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (79, 100, N'587056', CAST(N'2022-12-28' AS Date), 2184.5000, 2184.5000, 0.0000, 4, CAST(N'2023-02-09' AS Date), CAST(N'2023-02-07' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (80, 122, N'989319-467', CAST(N'2023-01-01' AS Date), 2318.0300, 2318.0300, 0.0000, 3, CAST(N'2023-01-31' AS Date), CAST(N'2023-01-29' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (81, 123, N'263253265', CAST(N'2023-01-02' AS Date), 26.2500, 26.2500, 0.0000, 3, CAST(N'2023-02-01' AS Date), CAST(N'2023-01-28' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (82, 94, N'203339-13', CAST(N'2023-01-05' AS Date), 17.5000, 17.5000, 0.0000, 2, CAST(N'2023-01-25' AS Date), CAST(N'2023-01-27' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (83, 95, N'111-92R-10093', CAST(N'2023-01-06' AS Date), 39.7700, 39.7700, 0.0000, 2, CAST(N'2023-01-26' AS Date), CAST(N'2023-01-22' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (84, 123, N'963253258', CAST(N'2023-01-06' AS Date), 111.0000, 111.0000, 0.0000, 3, CAST(N'2023-02-05' AS Date), CAST(N'2023-02-05' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (85, 123, N'963253271', CAST(N'2023-01-07' AS Date), 158.0000, 158.0000, 0.0000, 3, CAST(N'2023-02-06' AS Date), CAST(N'2023-02-11' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (86, 123, N'963253230', CAST(N'2023-01-07' AS Date), 739.2000, 739.2000, 0.0000, 3, CAST(N'2023-02-06' AS Date), CAST(N'2023-02-06' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (87, 123, N'963253244', CAST(N'2023-01-08' AS Date), 60.0000, 60.0000, 0.0000, 3, CAST(N'2023-02-07' AS Date), CAST(N'2023-02-09' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (88, 123, N'963253239', CAST(N'2023-01-08' AS Date), 147.2500, 147.2500, 0.0000, 3, CAST(N'2023-02-07' AS Date), CAST(N'2023-02-11' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (90, 123, N'963253252', CAST(N'2023-01-12' AS Date), 38.7500, 38.7500, 0.0000, 3, CAST(N'2023-02-11' AS Date), CAST(N'2023-02-11' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (91, 95, N'111-92R-10095', CAST(N'2023-01-15' AS Date), 32.7000, 32.7000, 0.0000, 2, CAST(N'2023-02-04' AS Date), CAST(N'2023-02-06' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (92, 117, N'111897', CAST(N'2023-01-15' AS Date), 16.6200, 16.6200, 0.0000, 3, CAST(N'2023-02-14' AS Date), CAST(N'2023-02-14' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (93, 123, N'4-327-7357', CAST(N'2023-01-16' AS Date), 162.7500, 162.7500, 0.0000, 3, CAST(N'2023-02-15' AS Date), CAST(N'2023-02-11' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (95, 82, N'C73-24', CAST(N'2023-01-19' AS Date), 600.0000, 600.0000, 0.0000, 2, CAST(N'2023-02-08' AS Date), CAST(N'2023-02-13' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (96, 110, N'P-0259', CAST(N'2023-01-19' AS Date), 26881.4000, 26881.4000, 0.0000, 3, CAST(N'2023-02-18' AS Date), CAST(N'2023-02-20' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (97, 90, N'97-1024A', CAST(N'2023-01-20' AS Date), 356.4800, 356.4800, 0.0000, 2, CAST(N'2023-02-09' AS Date), CAST(N'2023-02-07' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (103, 122, N'989319-417', CAST(N'2023-01-23' AS Date), 2051.5900, 2051.5900, 0.0000, 3, CAST(N'2023-02-22' AS Date), CAST(N'2023-02-24' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (104, 123, N'263253243', CAST(N'2023-01-23' AS Date), 44.4400, 44.4400, 0.0000, 3, CAST(N'2023-02-22' AS Date), CAST(N'2023-02-24' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (106, 110, N'0-2060', CAST(N'2023-01-24' AS Date), 23517.5800, 21221.6300, 2295.9500, 3, CAST(N'2023-02-23' AS Date), CAST(N'2023-02-27' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (107, 122, N'989319-447', CAST(N'2023-01-24' AS Date), 3689.9900, 3689.9900, 0.0000, 3, CAST(N'2023-02-23' AS Date), CAST(N'2023-02-19' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (108, 123, N'963253240', CAST(N'2023-01-24' AS Date), 67.0000, 67.0000, 0.0000, 3, CAST(N'2023-02-23' AS Date), CAST(N'2023-02-23' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (109, 121, N'97/222', CAST(N'2023-01-25' AS Date), 1000.4600, 1000.4600, 0.0000, 3, CAST(N'2023-02-24' AS Date), CAST(N'2023-02-22' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (111, 123, N'263253257', CAST(N'2023-01-30' AS Date), 22.5700, 22.5700, 0.0000, 3, CAST(N'2023-03-01' AS Date), CAST(N'2023-03-03' AS Date))
    INSERT PaidInvoices (InvoiceID, VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal, PaymentTotal, CreditTotal, TermsID, InvoiceDueDate, PaymentDate) VALUES (114, 123, N'963253249', CAST(N'2023-02-02' AS Date), 127.7500, 127.7500, 0.0000, 3, CAST(N'2023-03-01' AS Date), CAST(N'2023-03-04' AS Date))
    SET IDENTITY_INSERT PaidInvoices OFF
                

Un'unione che combina i dati delle fatture di due tabelle diverse.

    USE AP
    GO
    SELECT 'Active' AS Source, InvoiceNumber, InvoiceDate, InvoiceTotal
        FROM Activeinvoices
        WHERE InvoiceDate >= '2022-12-15'
    UNION
        SELECT 'Paid' AS Source, InvoiceNumber, InvoiceDate, InvoiceTotal
        FROM Paidinvoices
        WHERE InvoiceDate >= '2022-12-15'
    ORDER BY InvoiceTotal DESC
                

Descrizione

Unioni che combinano i dati della stessa tabella

L'esempio qui sotto mostra come utilizzare le unioni per combinare i dati di una singola tabella. Nel primo esempio, le righe della tabella Fatture che hanno un saldo da pagare vengono combinate con le righe della stessa tabella che sono state pagate per intero. Come nell'esempio precedente, all'inizio di ogni tabella intermedia viene aggiunta una colonna denominata Source. In questo modo, il risultato finale indica se ogni fattura è attiva o pagata. Il secondo esempio di questa figura mostra come si può utilizzare un'unione con i dati uniti da due tabelle. In questo caso, ogni istruzione SELECT unisce i dati delle tabelle Fatture e Venditori. La prima istruzione SELECT recupera le fatture con totali superiori a 10.000 dollari. Quindi calcola un pagamento pari al 33% del totale della fattura. Le altre due istruzioni SELECT sono simili. La seconda recupera le fatture con un totale compreso tra 500 e 10.000 dollari e calcola un pagamento del 50%. La terza recupera le fatture con un totale inferiore a 500 dollari e imposta il pagamento al 100% del totale. Anche se questo è un po' irrealistico, aiuta a illustrare la flessibilità delle operazioni con le unioni. Si noti che in questo esempio vengono assegnati gli stessi alias di colonna in ogni istruzione SELECT. Anche se gli alias della seconda e terza istruzione SELECT non hanno alcun effetto sulla query, credo che rendano la query più facile da leggere. In particolare, rende facile vedere che le tre istruzioni SELECT hanno lo stesso numero e lo stesso tipo di colonne.

Un'unione che combina le informazioni della tabella Fatture

    USE AP
    GO
        SELECT 'Active' AS Source, InvoiceNumber, InvoiceDate, InvoiceTotal
        FROM Invoices
        -- fatture con un saldo da pagare
        WHERE (InvoiceTotal - PaymentTotal - CreditTotal) > 0
    UNION
        SELECT 'Paid' AS Source, InvoiceNumber, InvoiceDate, InvoiceTotal
        FROM Invoices
        -- fatture pagate per intero
        WHERE (InvoiceTotal - PaymentTotal - CreditTotal) <= 0
    ORDER BY InvoiceTotal DESC
                

Un'unione che combina i dati di pagamento dalle stesse tabelle unite

    USE AP
    GO
        SELECT InvoiceNumber, VendorName, '33% Payment' AS PaymentType,
            InvoiceTotal AS Total, (InvoiceTotal * 0.333) AS Payment
        FROM Invoices JOIN Vendors
            ON Invoices.VendorID = Vendors.VendorID
        WHERE InvoiceTotal > 10000
    UNION
        SELECT InvoiceNumber, VendorName, '50% Payment' AS PaymentType,
            InvoiceTotal AS Total, (InvoiceTotal * 0.5) AS Payment
        FROM Invoices JOIN Vendors
            ON Invoices.VendorID = Vendors.VendorID
        WHERE InvoiceTotal BETWEEN 500 AND 10000
    UNION
        SELECT InvoiceNumber, VendorName, 'Full amount' AS PaymentType,
            InvoiceTotal AS Total, InvoiceTotal AS Payment
        FROM Invoices JOIN Vendors
            ON Invoices.VendorID = Vendors.vendorID
        WHERE InvoiceTotal < 500
    ORDER BY PaymentType, VendorName, InvoiceNumber
                

Come utilizzare gli operatori EXCEPT e INTERSECT

Gli operatori EXCEPT e INTERSECT sono stati introdotti con SQL Server 2005. Come l'operatore UNION, gli operatori EXCEPT e INTERSECT funzionano con due o più insiemi di risultati, come mostrato nell'esempio seguente. Per questo motivo, tutti e tre questi operatori possono essere definiti operatori di insiemi. Inoltre, gli operatori EXCEPT seguono molte delle stesse regole dell'operatore UNION. La prima query mostrata in questo esempio utilizza l'operatore EXCEPT per restituire i nomi e i cognomi di tutti i clienti di un'azienda, ad eccezione dei clienti il cui nome e cognome sono presenti anche nella tabella Dipendenti. Poiché Thomas Hardy è l'unico nome uguale in entrambe le tabelle, questa è l'unica riga che viene esclusa dall'insieme dei risultati della query che precede l'operatore EXCEPT. La seconda query utilizza l'operatore INTERSECT per restituire il nome e il cognome di tutti i clienti della tabella Clienti il cui nome e cognome sono presenti anche nella tabella Dipendenti. Poiché Thomas Hardy è l'unico nome presente in entrambe le tabelle, questa è l'unica riga restituita nel set di risultati di questa query. Quando si utilizzano gli operatori EXCEPT e INTERSECT, bisogna seguire molte delle stesse regole che si devono seguire quando si lavora con l'operatore UNION. Tanto per cominciare, entrambe le istruzioni collegate da questi operatori devono restituire lo stesso numero di colonne. Inoltre, i tipi di dati per colonne devono essere compatibili. Infine, quando due query sono unite da un operatore EXCEPT o INTERSECT, i nomi delle colonne nell'insieme dei risultati finale sono presi dalla prima query. Ecco perché la clausola ORDER BY utilizza la colonna CustomerLast specificata dalla prima query invece della colonna LastName specificata dalla seconda query. Se si comprende il funzionamento dell'operatore UNION non dovrebbe essere difficile capire queste regole. Anche se spesso è possibile ottenere lo stesso insieme di risultati utilizzando una join interna o una subquery al posto dell'operatore UNION. o una sottoquery al posto degli operatori EXCEPT e INTERSECT, questi operatori sono un'utile funzione di SQL Server che può facilitare il confronto tra due insiemi di risultati.

La sintassi per le operazioni EXCEPT e INTERSECT

        SELECT_statement_l
    {EXCEPT I INTERSECT}
        SELECT_statement_2
    [ORDER BY order_by_list]
                

Creare la tabella Customers

    USE AP
    GO                    
    -- create the Customers table
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE Customers (
        CustID int IDENTITY(1,1) NOT NULL,
        CustomerLast nvarchar(30) NULL,
        CustomerFirst nvarchar(30) NULL,
        CustAddr nvarchar(60) NULL,
        CustCity nvarchar(15) NULL,
        CustState nvarchar(15) NULL,
        CustZip nvarchar(10) NULL,
        CustPhone nvarchar(24) NULL,
        CONSTRAINT PK_Customers PRIMARY KEY CLUSTERED 
        (
            CustID ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
    )
    GO
                

Inserire le righe nella tabella Customers

    USE AP
    GO
    SET IDENTITY_INSERT Customers ON 
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (1, N'Anders', N'Maria', N'345 Winchell Pl', N'Anderson', N'IN', N'46014', N'(765) 555-7878')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (2, N'Trujillo', N'Ana', N'1298 E Smathers St', N'Benton', N'AR', N'72018', N'(501) 555-7733')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (3, N'Moreno', N'Antonio', N'6925 N Parkland Ave', N'Puyallup', N'WA', N'98373', N'(253) 555-8332')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (4, N'Hardy', N'Thomas', N'83 d''Urberville Ln', N'Casterbridge', N'GA', N'31209', N'(478) 555-1139')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (5, N'Berglund', N'Christina', N'22717 E 73rd Ave', N'Dubuque', N'IA', N'52004', N'(319) 555-1139')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (6, N'Moos', N'Hanna', N'1778 N Bovine Ave', N'Peoria', N'IL', N'61638', N'(309) 555-8755')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (7, N'Citeaux', N'Fred', N'1234 Main St', N'Normal', N'IL', N'61761', N'(309) 555-1914')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (8, N'Summer', N'Martin', N'1877 Ete Ct', N'Frogtown', N'LA', N'70563', N'(337) 555-9441')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (9, N'Lebihan', N'Laurence', N'717 E Michigan Ave', N'Chicago', N'IL', N'60611', N'(312) 555-9441')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (10, N'Lincoln', N'Elizabeth', N'4562 Rt 78 E', N'Vancouver', N'WA', N'98684', N'(360) 555-2680')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (32, N'Snyder', N'Howard', N'2732 Baker Blvd.', N'Eugene', N'OR', N'97403', N'(503) 555-7555')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (36, N'Latimer', N'Yoshi', N'City Center Plaza 516 Main St.', N'Elgin', N'OR', N'97827', N'(503) 555-6874')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (43, N'Steel', N'John', N'12 Orchestra Terrace', N'Walla Walla', N'WA', N'99362', N'(509) 555-7969')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (45, N'Yorres', N'Jaime', N'87 Polk St. Suite 5', N'San Francisco', N'CA', N'94117', N'(415) 555-5938')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (48, N'Wilson', N'Fran', N'89 Chiaroscuro Rd.', N'Portland', N'OR', N'97219', N'(503) 555-9573')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (55, N'Phillips', N'Rene', N'2743 Bering St.', N'Anchorage', N'AK', N'99508', N'(907) 555-7584')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (65, N'Wilson', N'Paula', N'2817 Milton Dr.', N'Albuquerque', N'NM', N'87110', N'(505) 555-5939')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (71, N'Pavarotti', N'Jose', N'187 Suffolk Ln.', N'Boise', N'ID', N'83720', N'(208) 555-8097')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (75, N'Braunschweiger', N'Art', N'P.O. Box 555', N'Lander', N'WY', N'82520', N'(307) 555-4680')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (77, N'Nixon', N'Liz', N'89 Jefferson Way Suite 2', N'Providence', N'RI', N'02909', N'(401) 555-3612')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (78, N'Wong', N'Liu', N'55 Grizzly Peak Rd.', N'Butte', N'MT', N'59801', N'(406) 555-5834')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (82, N'Nagy', N'Helvetius', N'722 DaVinci Blvd.', N'Concord', N'MA', N'01742', N'(351) 555-1219')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (89, N'Jablonski', N'Karl', N'305 - 14th Ave. S. Suite 3B', N'Seattle', N'WA', N'98128', N'(206) 555-4112')
    INSERT Customers (CustID, CustomerLast, CustomerFirst, CustAddr, CustCity, CustState, CustZip, CustPhone) VALUES (92, N'Chelan', N'Donna', N'2299 E Baylor Dr', N'Dallas', N'TX', N'75224', N'(469) 555-8828')
    SET IDENTITY_INSERT Customers OFF
                

Una query che esclude le righe dalla prima query se sono presenti anche nella seconda query

    USE AP
    GO
        SELECT CustomerFirst, CustomerLast
        FROM Customers
    EXCEPT
        SELECT FirstName, LastName
        FROM Employees
    ORDER BY CustomerLast
                

Una query che include solo le righe presenti in entrambe le query.

    USE AP
    GO
        SELECT CustomerFirst, CustomerLast
        FROM Customers
    INTERSECT
        SELECT FirstName, LastName
        FROM Employees
                

Descrizione

Prospettiva

In questa lezione si sono apprese diverse tecniche per combinare i dati di due o più tabelle in un unico insieme di risultati. In particolare, si è appreso come utilizzare la sintassi di SQL-92 per combinare i dati utilizzando i join interni. Di tutte le tecniche presentate in questo capitolo, questa è quella che utilizzerete più spesso. Per questo motivo, prima di continuare, è bene essere sicuri di averla compresa a fondo.