Query to bring 1 Parent record and in it can contain multiple child records (performance)

Assuming that for the customer I can still put more joins as not only sales, and in the result of this query bring much more records. Is this a performatic way to work or would it be better for me to query each separate table and populate my client object in C#?

CREATE TABLE CLIENTE 
(
    ID_CLIENTE INT PRIMARY KEY IDENTITY (1, 1),
    NOME_CLIENTE VARCHAR(200) NOT NULL
)
INSERT INTO CLIENTE (NOME_CLIENTE) VALUES ('TESTE 1')

CREATE TABLE VENDA
(
    ID_VENDA INT PRIMARY KEY IDENTITY (1, 1),
    ID_CLIENTE INT NOT NULL
)
ALTER TABLE VENDA ADD CONSTRAINT PK_VENDA_CLIENTE PRIMARY KEY (ID_VENDA, ID_CLIENTE)

INSERT INTO CLIENTE (ID_CLIENTE) VALUES ((SELECT ID_CLIENTE FROM CLIENTE WHERE NOME_CLIENTE = 'TESTE 1'))

CREATE TABLE PRODUTO
(
    ID_PRODUTO INT PRIMARY KEY IDENTITY (1, 1),
    NOME_PRODUTO VARCHAR(200) NOT NULL,
    VALOR_PRODUTO DECIMAL(10,4) NOT NULL
)

INSERT INTO PRODUTO (NOME_PRODUTO, VALOR_PRODUTO) VALUES ('TOMATE', 10)
INSERT INTO PRODUTO (NOME_PRODUTO, VALOR_PRODUTO) VALUES ('ABACAXI', 20)
INSERT INTO PRODUTO (NOME_PRODUTO, VALOR_PRODUTO) VALUES ('UVA', 30)
INSERT INTO PRODUTO (NOME_PRODUTO, VALOR_PRODUTO) VALUES ('MORANGO', 40)
INSERT INTO PRODUTO (NOME_PRODUTO, VALOR_PRODUTO) VALUES ('ALFACE', 50)

CREATE TABLE VENDAPRODUTO
(
    ID_VENDA INT NOT NULL,
    ID_PRODUTO INT NOT NULL,
    QUANTIDADE INT NOT NULL,
    VALOR_PRODUTO INT NOT NULL
)

INSERT INTO VENDAPRODUTO (ID_PRODUTO, QUANTIDADE, VALOR_PRODUTO) VALUES ((SELECT ID_PRODUTO FROM PRODUTO WHERE NOME_PRODUTO = 'TOMATE'), 1, 10)
INSERT INTO VENDAPRODUTO (ID_PRODUTO, QUANTIDADE, VALOR_PRODUTO) VALUES ((SELECT ID_PRODUTO FROM PRODUTO WHERE NOME_PRODUTO = 'ABACAXI'), 2, 20)
INSERT INTO VENDAPRODUTO (ID_PRODUTO, QUANTIDADE, VALOR_PRODUTO) VALUES ((SELECT ID_PRODUTO FROM PRODUTO WHERE NOME_PRODUTO = 'UVA'), 7, 30)
INSERT INTO VENDAPRODUTO (ID_PRODUTO, QUANTIDADE, VALOR_PRODUTO) VALUES ((SELECT ID_PRODUTO FROM PRODUTO WHERE NOME_PRODUTO = 'MORANGO'), 4, 40)
INSERT INTO VENDAPRODUTO (ID_PRODUTO, QUANTIDADE, VALOR_PRODUTO) VALUES ((SELECT ID_PRODUTO FROM PRODUTO WHERE NOME_PRODUTO = 'ALFACE'), 2, 50)

SELECT CLIENTE.ID_CLIENTE,
      CLIENTE.NOME_CLIENTE,
      VENDAPRODUTO.ID_PRODUTO,
      PRODUTO.NOME_PRODUTO,
      VENDAPRODUTO.QUANTIDADE,
      VENDAPRODUTO.VALOR_PRODUTO
 FROM CLIENTE CLIENTE
 LEFT JOIN VENDA VENDA ON VENDA.ID_CLIENTE = CLIENTE.ID_CLIENTE
 LEFT JOIN VENDAPRODUTO VENDAPRODUTO ON VENDAPRODUTO.ID_VENDA = VENDA.ID_VENDA 
 LEFT JOIN PRODUTO PRODUTO ON PRODUTO.ID_PRODUTO = VENDAPRODUTO.ID_PRODUTO
WHERE CLIENTE.ID_CLIENTE = 1

Result

/* 

ID_CLIENTE | NOME_CLIENTE | ID_PRODUTO | NOME_PRODUTO | QUANTIDADE | VALOR_PRODUTO
1          | TESTE 1      | 1          | TOMATE       | 1          | 10
1          | TESTE 1      | 2          | ABACAXI      | 2          | 20
1          | TESTE 1      | 3          | UVA          | 7          | 30
1          | TESTE 1      | 4          | MORANGO      | 4          | 40
1          | TESTE 1      | 5          | ALFACE       | 2          | 50

*/
Author: Nicola Bogar, 2019-11-05

1 answers

Hello, Nicola!

When the data volume is too large and I have the possibility to reduce the volume of data that I will have to handle, I use CTEs(Common Table Expressions).

I Create one or more CTEs with data ranges, already filtered by the conditions I want (date range or the code of a product, for example).

CTEs work as in-memory tables and they exist only in the execution of your query. They are not created in TEMPDB, equal to a temporary table, which helps in performance. Its basic difference to a temporary table is the impossibility of performing UPDATES, DELETES and INSERTS, which does not seem to be a problem for your situation. Once I have filtered CTEs, I do join between them and filter something else that is needed and do groupings.

The documentation of using CTEs is in this Link , I recommend you take a look.

As for the grouping part in C#, I do not recommend, you it would carry a lot of data between the bank and application. The ideal is to already return your ideal SQL resultset and only display in your application.

In the company where I work as a DEV, we have views and even procedures that are called with the Dapper(a simple and fast ORM, we use it only for reporting. Is the ORM used here in StackOverflow) and the resultset is rendered on the user's screen.

Here also has a Step By Step legal use of CTEs, in the blog of Dirceu Resende (Microsoft MVP in the data area).

Hope I helped!

 -1
Author: Herbert Vianna, 2020-01-04 23:16:12