Usuário com melhor resposta
Exibir todas as datas buscadas em uma linha mesmo que o conteúdo seja nulo

Pergunta
-
Olá,
Tenho um sistema em c# que precisa exibir a data e a quantidade x de ocorrências dentro do intervalo setado pelo usuário, acontece que da forma que fiz o sistema, se não houver uma ocorrência em uma determinada data, ela não volta com resultado 0 da query do SQL .
EX:
Dia ---- Ocorrências
01 ---- 5
02 ---- 2
03 ---- 0
04 ---- 5
Dessa forma a tabela gerada na consulta não me retorna a linha com a data 03 - 0 ocorrência.
Gostaria de saber como fazer pra que essa data apareça no resultado do sql.
Abaixo está a minha query
select v.local AS EQUIP, CAST(v.data AS DATE) AS DATA, COALESCE (SUM(CASE WHEN c.classe = 'A' AND v.detector = 0 THEN 1 ELSE NULL END), 0) AS A1, COALESCE (SUM(CASE WHEN c.classe = 'A' AND
v.detector = 1 THEN 1 ELSE NULL END), 0) AS A2, COALESCE (SUM(CASE WHEN c.classe = 'A' AND v.detector = 2 THEN 1 ELSE NULL END), 0) AS A3, COALESCE (SUM(CASE WHEN c.classe = 'A' AND
v.detector = 3 THEN 1 ELSE NULL END), 0) AS A4FROM veiculo AS v INNER JOIN
classe AS c ON v.id_classe = c.id_classe
WHERE v.data BETWEEN @p1 AND @p2
GROUP BY v.local
ORDER BY EQUIP
Preciso que me retorne todas as datas entre os parâmetros mesmo que não tenha ocorrências.Obrigado.
- Editado Gabriel FFarias sexta-feira, 22 de maio de 2015 20:09
Respostas
-
Bom pessoal consegui resolver dentro do código c# mesmo,
Pra quem um dia tiver o mesmo problema, fica ai a solução:
Converti a datatable resultada pelo sql em uma list <Lista>, em seguida fiz outra list <Datas> com todas as datas entre os parâmetros e setando 0 para as classes.
Depois fiz um for dentro de outro for pra apagar as datas da list <Datas> que tenham a mesma data na lista <Lista> deixando assim somente as datas faltantes.
Depois fiz um AddRange entre os 2 lists e obtive meu resultado.
Obrigado a todos!
- Marcado como Resposta Gabriel FFarias segunda-feira, 25 de maio de 2015 14:24
Todas as Respostas
-
Gabriel, troca o INNER JOIN pelo LEFT JOIN:
select v.local AS EQUIP, CAST(v.data AS DATE) AS DATA, COALESCE (SUM(CASE WHEN c.classe = 'A' AND v.detector = 0 THEN 1 ELSE NULL END), 0) AS A1, COALESCE (SUM(CASE WHEN c.classe = 'A' AND v.detector = 1 THEN 1 ELSE NULL END), 0) AS A2, COALESCE (SUM(CASE WHEN c.classe = 'A' AND v.detector = 2 THEN 1 ELSE NULL END), 0) AS A3, COALESCE (SUM(CASE WHEN c.classe = 'A' AND v.detector = 3 THEN 1 ELSE NULL END), 0) AS A4 FROM veiculo AS v LEFT JOIN classe AS c ON v.id_classe = c.id_classe WHERE v.data BETWEEN @p1 AND @p2 GROUP BY v.local ORDER BY EQUIP
-
Experimente com CTE:
declare @min int = 1, @max int = 31 ;with usuario_cte (id ) as
(
select @min as ID
union all
select A.id+1 as ID from usuario_cte A where A.id <= @max
)
select ID, count(id_usuario) from usuario_cte A left join cont.TAB_usuario B on A.id = DATEPART(day,data_cadastro)
group by ID -
Gabriel, troca o INNER JOIN pelo LEFT JOIN:
select v.local AS EQUIP, CAST(v.data AS DATE) AS DATA, COALESCE (SUM(CASE WHEN c.classe = 'A' AND v.detector = 0 THEN 1 ELSE NULL END), 0) AS A1, COALESCE (SUM(CASE WHEN c.classe = 'A' AND v.detector = 1 THEN 1 ELSE NULL END), 0) AS A2, COALESCE (SUM(CASE WHEN c.classe = 'A' AND v.detector = 2 THEN 1 ELSE NULL END), 0) AS A3, COALESCE (SUM(CASE WHEN c.classe = 'A' AND v.detector = 3 THEN 1 ELSE NULL END), 0) AS A4 FROM veiculo AS v LEFT JOIN classe AS c ON v.id_classe = c.id_classe WHERE v.data BETWEEN @p1 AND @p2 GROUP BY v.local ORDER BY EQUIP
-
Experimente com CTE:
declare @min int = 1, @max int = 31 ;with usuario_cte (id ) as
(
select @min as ID
union all
select A.id+1 as ID from usuario_cte A where A.id <= @max
)
select ID, count(id_usuario) from usuario_cte A left join cont.TAB_usuario B on A.id = DATEPART(day,data_cadastro)
group by ID -
-
-
José,
Sim eu gostaria que um dia que não houvesse registro fosse exibido a data, com valor 0 em cada coluna A.
Acontece que simplifiquei aqui a consulta pois as classes vão Até P e ficaria um código gigante, mas o restante é basicamente o mesmo que acontece na A. Por isso ocorre a junção entre veículo e local, para verificar qual é o id da classe que corresponde o id no veículo.
A tabela veículo grava data e hora.
Os parâmetros @p1 e @p2 recebem um datetime modificado via código c#, no caso do @p1 ele recebe a data inicial informada pelo usuário com hora 00:00:00 e o @p2 recebe a data final com 23:59:59
- Editado Gabriel FFarias segunda-feira, 25 de maio de 2015 11:01
-
Bom pessoal consegui resolver dentro do código c# mesmo,
Pra quem um dia tiver o mesmo problema, fica ai a solução:
Converti a datatable resultada pelo sql em uma list <Lista>, em seguida fiz outra list <Datas> com todas as datas entre os parâmetros e setando 0 para as classes.
Depois fiz um for dentro de outro for pra apagar as datas da list <Datas> que tenham a mesma data na lista <Lista> deixando assim somente as datas faltantes.
Depois fiz um AddRange entre os 2 lists e obtive meu resultado.
Obrigado a todos!
- Marcado como Resposta Gabriel FFarias segunda-feira, 25 de maio de 2015 14:24