Jump to content
jafm

[Resolvido] Erro após ter colocado inner join

Recommended Posts

jafm

Olá,

Tinha uma query que devolvia o produto no top num determinado mês.

Só que agora existe a necessidade de colocar a imagem nesse produto. Então ai surge o meu erro

[/size]
select *  from
(
select top 1 Produto, Qtd, [Fotos].[dbo].[Fotos].Imagem
from dbo.[fnProdutoTop]('01-01-2013','31-01-2013') inner join [Fotos].[dbo].[Fotos] on Produto=ImagemProduto
order by qtd desc
union
select top 1 Produto, Qtd, [ForevaGIFotos].[dbo].[Fotos].Imagem
from dbo.[fnProdutoTop]('01-02-2013','28-02-2013') inner join [Fotos].[dbo].[Fotos] on Produto=ImagemProduto
order by qtd desc
) T order by qtd desc

o erro que está a dar é "The image data type cannot be selected as DISTINCT because it is not comparable."

No entanto se eu fizer apenas

select top 1 Produto, Qtd, [Fotos].[dbo].[Fotos].Imagem
from dbo.[fnProdutoTop]('01-01-2013','31-01-2013') inner join [Fotos].[dbo].[Fotos] on Produto=ImagemProduto
order by qtd desc

o erro já não parece... O que estou a fazer de errado no inner join ou no union?

Share this post


Link to post
Share on other sites
AntonioMateus

Por defeito o "union" faz "Distinct" e para isso tem que comparar os campos, mas não consegue comparar campos do tipo "Image".

Podes tentar usar "Union All"...

Se não resolver faz 1º o union sem as imagens e fazes o inner join à tabela Fotos apenas com a derivada T.

Share this post


Link to post
Share on other sites
Rechousa

Olá,

Experimenta fazer assim (não testei):

SELECT Produto, Qtd, I.IMAGEM
FROM
(
SELECT TOP 1 Produto, Qtd
	FROM dbo.[FNPRODUTOTOP]('01-01-2013','31-01-2013')
	ORDER BY QTD DESC
UNION
SELECT TOP 1 Produto, Qtd
	FROM dbo.[FNPRODUTOTOP]('01-02-2013','28-02-2013')
	ORDER BY QTD DESC
) P
INNER JOIN [FOTOS].[DBO].[FOTOS] I ON P.Produto = I.ImagemProduto;

O que isto faz é o seguinte:

- Em primeiro lugar retorna o TOP Produto de Janeiro

- Faz o Union com o TOP Produto de Fevereiro

- Repara que apenas está a ser usado o que deverá ser o ID do Produto (o teu campo Produto) e a quantidade;

- A este conjunto de 1 ou 2 registos (se forem produtos iguais ou diferentes) é feito um JOIN com a tabela das imagens;

- Finalmente é retornado o resultado.

Deverá funcionar e deverá ser mais eficiente do que tinhas anteriormente.

Espero ter ajudado,

Edited by Rechousa

Pedro Martins

Sharing is Knowledge!

http://www.linkedin.com/in/rechousa

Share this post


Link to post
Share on other sites
Rechousa

Olá,

Pois, retornou um erro, motivado pela ordenação com UNION's (em que deverás definir o ORDER BY no último UNION).

Construí uma demo, baseada nas informações que disponibilizaste (e aparentemente funcionou).

Aqui vai:

-- ====================================================================================
-- Author	  : Pedro Martins / https://www.linkedin.com/in/rechousa
-- Project	 : Demo Portugal a programar
-- Create date : 2013-06-14
-- Description : Demonstração Portugal a Programar
-- Returns	 : ---
-- Remarks	 : Não está a validar se as tabelas existem ou não
-- ====================================================================================
USE [tempdb];
GO

SET NOCOUNT ON;

-- Cria uma tabela de vendas
CREATE TABLE [dbo].[Vendas] (
   id INT,
   Qtd INT,
   DataVenda DATETIME
);
GO

-- Cria uma tabela de imagens
CREATE TABLE [dbo].[imagens] (
   ImagemProduto INT,
   Imagem VARBINARY(MAX)
);
GO

-- Cria a função ProdutoTop que retorna o produto de top de vendas dentro de um intervalo de datas
CREATE FUNCTION [dbo].[FNPRODUTOTOP] (
   @DataInicio DATETIME,
   @DataFim DATETIME
)
RETURNS @SomatorioVendas TABLE (
   Produto INT,
   Qtd INT
)
AS
BEGIN

INSERT INTO @SomatorioVendas
SELECT id, SUM(Qtd) AS Qtd
   FROM [dbo].[Vendas]
   WHERE DataVenda BETWEEN @DataInicio AND @DataFim
   GROUP BY id
   ORDER BY Qtd DESC;
RETURN;
END
GO

-- Insere registos de teste em vendas
INSERT INTO [dbo].[Vendas] VALUES
   (1, 99, '2013-01-01'),
   (1, 10, '2013-02-01'),
   (3, 5, '2013-01-08'),
   (3, 9, '2013-02-12'),
   (6, 23, '2013-01-08'),
   (6, 23, '2013-02-04');
GO

-- Insere registos de teste em Imagens
INSERT INTO [dbo].[imagens] VALUES
   (1, 0x123),
   (3, 0x999999),
   (6, 0x456);
GO





-- Execução da query:
SELECT Produto, Qtd, I.IMAGEM
   FROM
   (
       SELECT TOP 1 Produto, Qtd
           FROM dbo.[FNPRODUTOTOP]('20130101', '20130131')
       UNION
       SELECT TOP 1 Produto, Qtd
           FROM dbo.[FNPRODUTOTOP]('20130201', '20130228')
       ORDER BY QTD DESC
   ) P
   INNER JOIN Imagens I ON P.Produto = I.ImagemProduto;
GO

Espero ter ajudado.


Pedro Martins

Sharing is Knowledge!

http://www.linkedin.com/in/rechousa

Share this post


Link to post
Share on other sites
jafm

Ainda não consegui...

SELECT ArtigoRef, Case Month(Cast('01-01-2013 00:01' as char)) WHEN '1' THEN 'Jan' WHEN '2' THEN 'Fev' WHEN '3' THEN 'Mar' WHEN '4' THEN 'Abr' WHEN '5' THEN 'Mai' WHEN '6' THEN 'Jun' WHEN '7' THEN 'Jul' WHEN '8' THEN 'Ago' WHEN '9' THEN 'Set' WHEN '10' THEN 'Out' WHEN '11' THEN 'Nov' WHEN '12' THEN 'Dez' end as ano, Qnt, I.IMAGEM
--select *
 FROM
(
 SELECT TOP 1 ArtigoRef,Case Month(Cast('01-01-2013 00:01' as char)) WHEN '1' THEN 'Jan' WHEN '2' THEN 'Fev' WHEN '3' THEN 'Mar' WHEN '4' THEN 'Abr' WHEN '5' THEN 'Mai' WHEN '6' THEN 'Jun' WHEN '7' THEN 'Jul' WHEN '8' THEN 'Ago' WHEN '9' THEN 'Set' WHEN '10' THEN 'Out' WHEN '11' THEN 'Nov' WHEN '12' THEN 'Dez' end as ano, Qnt
		 FROM dbo.[fnVendasTop] ('0','01-01-2013 00:01','01-31-2013 23:59')
		 ORDER BY Qnt DESC
 UNION
 SELECT top 1 ArtigoRef,Case Month(Cast('01-02-2013 00:01' as char)) WHEN '1' THEN 'Jan' WHEN '2' THEN 'Fev' WHEN '3' THEN 'Mar' WHEN '4' THEN 'Abr' WHEN '5' THEN 'Mai' WHEN '6' THEN 'Jun' WHEN '7' THEN 'Jul' WHEN '8' THEN 'Ago' WHEN '9' THEN 'Set' WHEN '10' THEN 'Out' WHEN '11' THEN 'Nov' WHEN '12' THEN 'Dez' end as ano, Qnt
		 FROM dbo.[fnVendasTop] ('0','01-02-2013 00:01','02-28-2013 23:59')
		 ORDER BY Qnt DESC
) P
 INNER JOIN [Fotos].[dbo].[Fotos] I ON P.CAST('0' AS NVARCHAR(1))+SUBSTRING(ArtigoRef,1,3)+SUBSTRING(ArtigoRef,5,4)+'.jpg' = I.ImagemNome

Dá me um erro ao no union

P.CAST('0' AS NVARCHAR(1))+SUBSTRING(ArtigoRef,1,3)+SUBSTRING(ArtigoRef,5,4)+'.jpg' = I.ImagemNome

Ou seja, ele não está a gostar muito do P.Cast

Edited by jafm

Share this post


Link to post
Share on other sites
AntonioMateus

Já viste a solução que o Rechousa colocou?!

É que não só não aproveitaste nada da query dele como a que tens está cheia de erros...

Além do

ON P.CAST('0' AS NVARCHAR(1))

, que não faz sentido,

continuas a ter um

Order by

dentro do Union, como já te disseram dentre do union só podes fazer order depois do último select

Por outro lado, não sendo erro, não faz sentido:

Case Month(Cast('01-01-2013 00:01' as char))
WHEN '1' THEN 'Jan'
WHEN '2' THEN 'Fev'
WHEN '3' THEN 'Mar'
WHEN '4' THEN 'Abr'
WHEN '5' THEN 'Mai'
WHEN '6' THEN 'Jun'
WHEN '7' THEN 'Jul'
WHEN '8' THEN 'Ago'
WHEN '9' THEN 'Set'
WHEN '10' THEN 'Out'
WHEN '11' THEN 'Nov'
WHEN '12' THEN 'Dez'
end as ano

para que este código? Estás a fazer cast e case a um valor que já sabes qual é! porque não colocas logo 'Jan', também não faz sentido chamar a coluna de ano quando a valor é o mês...

Share this post


Link to post
Share on other sites
jafm

Olá,

Concordo contigo AntonioMateus.

Mas neste caso tenho que ter no código

ON '0'

porque senão ele não me vai buscar a foto.

Vou então colocar o código mais limpo, só que continuo com o problema de não conseguir buscar buscar o ArtigoRef com maior vendas, e apenas me devolve uma linha em vez de duas pois tenho 2 select...

SELECT ArtigoRef, Qnt, I.IMAGEM

 FROM
(
 SELECT TOP 1 ArtigoRef, Qnt
		 FROM dbo.[fnVendasTop] ('0','01-01-2013 00:01','01-31-2013 23:59')
		 UNION
 SELECT top 1 ArtigoRef, Qnt
		 FROM dbo.[fnVendasTop] ('0','01-02-2013 00:01','02-28-2013 23:59')
ORDER BY Qnt DESC
		 ) P
 INNER JOIN [Fotos].[dbo].[Fotos] I ON '0'+SUBSTRING(ArtigoRef,1,3)+SUBSTRING(ArtigoRef,5,4)+'.jpg' = I.ImagemNome

Edited by jafm

Share this post


Link to post
Share on other sites
AntonioMateus

Vê se isto te ajuda:

SELECT ArtigoRef, Qnt, I.IMAGEM
FROM
(
	 SELECT ArtigoRef, Qnt, '0'+SUBSTRING(ArtigoRef,1,3)+SUBSTRING(ArtigoRef,5,4)+'.jpg' as ImagemNome
	 FROM dbo.[fnVendasTop] ('0','01-01-2013 00:01','01-31-2013 23:59')
        where Qnt = (select max(Qnt) FROM dbo.[fnVendasTop] ('0','01-01-2013 00:01','01-31-2013 23:59'))

	 UNION all

	 SELECT ArtigoRef, Qnt, '0'+SUBSTRING(ArtigoRef,1,3)+SUBSTRING(ArtigoRef,5,4)+'.jpg' as ImagemNome
	 FROM dbo.[fnVendasTop] ('0','01-02-2013 00:01','02-28-2013 23:59')
        where Qnt = (select max(Qnt) FROM dbo.[fnVendasTop] ('0','01-02-2013 00:01','02-28-2013 23:59'))

	 ORDER BY Qnt DESC

) P
INNER JOIN [Fotos].[dbo].[Fotos] I ON I.ImagemNome = P.ImagemNome

Retirei o Top 1 para o caso de teres mais do que um com o valor máximo.

Edited by AntonioMateus

Share this post


Link to post
Share on other sites
jafm

Olá...

devolveu me este erro

The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.

Ao retirar o outro order by... o erro desaparece, mas não me devolve valor nenhum...

Edited by jafm

Share this post


Link to post
Share on other sites
Rechousa

Olá,

Experimenta assim:

SELECT ArtigoRef, Qnt, I.IMAGEM
FROM
(
   SELECT TOP 1 WITH TIES ArtigoRef, Qnt
       FROM dbo.[fnVendasTop] ('0','01-01-2013 00:01','01-31-2013 23:59')
       ORDER BY Qnt DESC
   UNION ALL
   SELECT top 1 WITH TIES ArtigoRef, Qnt
       FROM dbo.[fnVendasTop] ('0','01-02-2013 00:01','02-28-2013 23:59')
       ORDER BY Qnt DESC
) P
INNER JOIN [Fotos].[dbo].[Fotos] I ON I.ImagemNome = ('0'+SUBSTRING(P.ArtigoRef,1,3)+SUBSTRING(P.ArtigoRef,5,4)+'.jpg')

Pormenores:

- acrescentado hint WITH TIES.

Explicação: o hint WITH TIES permite o retorno de registos "empatados", ou seja, se tiveres apenas 1 produto com o máximo de quantidade, retorna esse produto. Se tiveres 10 retorna 10.

- a concatenação do nome da imagem passou para fora

Explicação: se tiveres que alterar as regras de concatenação para outro formato qualquer, só tens de alterar num só sítio. Ok, são apenas dois sítios, mas e se tiveres para todos os meses? Passam a ser 12. Além de que o código mais "clean" e, logo mais legível.

Espero ter ajudado,


Pedro Martins

Sharing is Knowledge!

http://www.linkedin.com/in/rechousa

Share this post


Link to post
Share on other sites
jafm

Olá, Rechousa.

Se realizar apenas este pedaço de codigo o resultado devolvido é o correcto.

SELECT top 1 WITH TIES ArtigoRef, Qnt
 FROM dbo.[fnVendasTop] ('0','01-02-2013 00:01','02-28-2013 23:59')
 ORDER BY Qnt DESC

Caso execute todo o codigo, não me é devolvido nenhum valor :(

será alguma coisa no inner join? ou então no order by

Edited by jafm

Share this post


Link to post
Share on other sites
Rechousa

Olá,

Experimenta sem o JOIN:

SELECT ArtigoRef, Qnt
FROM
(
   SELECT TOP 1 WITH TIES ArtigoRef, Qnt
       FROM dbo.[fnVendasTop] ('0','01-01-2013 00:01','01-31-2013 23:59')
       ORDER BY Qnt DESC
   UNION ALL
   SELECT top 1 WITH TIES ArtigoRef, Qnt
       FROM dbo.[fnVendasTop] ('0','01-02-2013 00:01','02-28-2013 23:59')
       WHERE Qnt = (SELECT MAX(Qnt) FROM dbo.[fnVendasTop] ('0','01-02-2013 00:01','02-28-2013 23:59'))
       ORDER BY Qnt DESC
) P

Pode ser a condição de join que esteja mal.


Pedro Martins

Sharing is Knowledge!

http://www.linkedin.com/in/rechousa

Share this post


Link to post
Share on other sites
jafm

Pois é mesmo o inner join...

Coloquei sem o inner join e já me devolveu os resultados...

Share this post


Link to post
Share on other sites
Rechousa

Agora, tens de ver qual é a expressão correta para fazer o JOIN, se bem que não recomendo usar o nome da imagem como join, deverias ter um ID de imagem, como um GUID (em SQL Server chama-se UNIQUEIDENTIFIER) ou INT.


Pedro Martins

Sharing is Knowledge!

http://www.linkedin.com/in/rechousa

Share this post


Link to post
Share on other sites
jafm

Pois, mas eu só consigo ir buscar a imagem dessa maneira através do nome da imagem :(

Share this post


Link to post
Share on other sites
Rechousa

Ok, então só precisas de colocar a expressão correta de JOIN e o problema deverá ficar resolvido.

Posso marcar o tópico como resolvido?

Edited by Rechousa

Pedro Martins

Sharing is Knowledge!

http://www.linkedin.com/in/rechousa

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.