SQL + Left Join

Asked

Viewed 87 times

-1

I have 3 tables produto, carrinhoProduto and venda I wanted to know the products that did not sell in the year 2015:

SELECT p.idProduto,p.descricao as 'Produto',datepart(year,v.dataVenda) as 'Ano'
FROM Venda v
INNER JOIN CarrinhoProduto cp ON v.idCarrinho = cp.idCarrinho
LEFT JOIN Produto p ON p.idProduto = cp.idProduto
WHERE cp.idProduto IS NULL AND datepart(year,GETDATE()) = 2015
GROUP BY p.idProduto, p.descricao, v.dataVenda

The result is all the products that were not sold, that is, from always 2016+2015+....etc., but only wanted the 2015 ones.

  • What exactly is the type of your date field in the table?

  • Great, the guy’s date

  • @Dexter which database you are using?

2 answers

2

In reality the best way would be with NOT EXISTS since the clause exists exactly for this purpose:

SELECT p.idProduto,
       p.descricao AS 'Produto',
       2015 AS 'Ano'
  FROM Produto p
 WHERE NOT EXISTS(SELECT
                    FROM Venda v
                         INNER JOIN CarrinhoProduto cp ON v.idCarrinho = cp.idCarrinho
                   WHERE cp.idProduto = p.idProduto
                     AND DATEPART(YEAR, v.dataVenda) = 2015)

Observing: as the year is set in a variable, it is probably not interesting to return it in this query.


EXISTS

The SQL EXISTS condition is used in Combination with a subquery and is considered to be met, if the subquery Returns at least one Row.

In free translation:

The EXISTS SQL condition is used in conjunction with a subquery and is deemed to be met if the subquery returns at least one line.

  • The problem is that the date is in the sale table, so this solution does not work. Thanks

  • @Dexter, you have to agree that it doesn’t make sense for you to get information from the sales table when you’re looking for something that shouldn’t be there

  • I have the following logic, Product-i dProduct int not null Identity(1,1), Description varchar(120) not null, idCategoria tinyint not null, precoUnitario decimal(6,2) not null, promocao int null, Cartprod got id cart and idProd and quantity. then on sale have id sale,idFunctioning, idCarrinho, dating etc

  • Particularly I don’t like subquery solutions, regardless of how they work, they should be avoided for performance reasons.

  • @Kennyrafael If misused affect performance even. In this case, any solution without subquery will make the outcome dependent on a sale. If you try a year that there is no sale no result will appear since you have an Internet with sale and this is completely incorrect. I suggest you read the answer to that question: Can subqueries decrease performance? Myth or truth?

  • I can only think of a solution for NOT EXISTS or NOT IN and there are researches where the result is more important than efficiency , it will run once and that’s it.

  • @Sorack, that’s what the left join.

  • @Kennyrafael O LEFT JOINserves to bring information to the left even if there is no right. In this case, it should not depend on sales. The solution with LEFT in this case is flawed as it presents the problem I explained in my last comment.

  • @Sorack, the left join is used perfectly in this case precisely for this reason, filtering the ano as I did in my reply, just add one more where where the result of the right just doesn’t exist, since he needs to know what he DIDN’T sell that year...

  • @Kennyrafael you make a FROM on the table vendas, will never bring any result in a year that has not yet had sale.

  • 1

    @Sorack, thank you very much, despite your misunderstanding regarding the use of LEFT JOIN On this issue, you made me realize that you were dealing wrong with @Dexter’s business rule, anyway, I think you got too hung up on that (business rule), and you didn’t understand what the feature could offer. I hope you understand how a constructive criticism, because both solutions work, there is no need to kill yourself for it.

  • @Kennyrafael quiet, I also have no intention of offending you, all I said was as constructive criticism also and no intention of attacking in any way

Show 7 more comments

2

If your field is one date, just filter with a simple operator:

SELECT p.idProduto, p.descricao as 'Produto', YEAR(v.dataVenda) as 'Ano'
FROM Produto p
LEFT JOIN Venda v ON p.idProduto = cp.idProduto
LEFT JOIN CarrinhoProduto cp ON v.idCarrinho = cp.idCarrinho
WHERE YEAR(v.dataVenda) <> 2015 OR v.dataVenda IS NULL
GROUP BY p.idProduto, v.dataVenda

Or using a BETWEEN:

SELECT p.idProduto, p.descricao as 'Produto', YEAR(v.dataVenda) as 'Ano'
FROM Produto p
LEFT JOIN Venda v ON p.idProduto = cp.idProduto
LEFT JOIN CarrinhoProduto cp ON v.idCarrinho = cp.idCarrinho
WHERE YEAR(v.dataVenda) NOT BETWEEN 2015 AND 2015 OR v.dataVenda IS NULL
GROUP BY p.idProduto, v.dataVenda

In this case, the ideal is that your main table(FROM), be it Produto instead of Venda, which consequently changes the order of JOINs of your inquiry, after that the first condition (in both queries) guarantees you will not bring products sold in the year of filtration and the second condition ensures that you will also bring products that have never been sold. I also removed the p.descricao of group by, since you are already grouping by p.idProduto.

  • I also tried it and it doesn’t work, alias or show anything, but if you take out Where cp.idProduct IS NULL and leave so Where YEAR(v.dataVenda) = 2015 it shows the products but the result is bad

  • @Dexter, I edited my answer! =)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.