Select Where IN all records

Asked

Viewed 160 times

4

inserir a descrição da imagem aquiGentlemen , will searched for days the answers to this doubt that I think is silly , but I could not.

I created a view that has Matricula | Name |Job |Shift | Centrocusto | Codtreina | Status

I made this select :

SELECT * FROM vw_treina_func TF WHERE TF.CodTreina IN (1,16,22,33,75,97110, 115, 158,161,164,173,)

This select is bringing employees who have one or other code training within the IN. What I need is for you to somehow just bring in the employees who have them all and not each other like this.

view has informing table trai_func Join table functionsJoin func_area

Follow the code of worked:

SELECT a.Codigo, a.descricao, fa.CentroCusto, f.MatriculaSese,r.Descricao, f.nome
FROM area a 
INNER JOIN treina_area ta ON ta.CodArea = a.Codigo 
INNER JOIN treina_func tf ON tf.CodTreina = ta.CodTreina 
INNER JOIN funcionarios f ON f.MatriculaSese = tf.MatriculaSese
INNER JOIN func_area fa ON f.MatriculaSese = fa.MatriculaSese
INNER JOIN area r ON r.Codigo = fa.CentroCusto
LEFT JOIN ( SELECT CodArea, Codtreina, (SELECT COUNT(DISTINCT iita.CodTreina) FROM treina_area iita WHERE iita.CodArea = ita.CodArea) numTreinos FROM treina_area ita ) TodosTreinosArea ON TodosTreinosArea.CodArea = ta.CodArea AND TodosTreinosArea.Codtreina = ta.CodTreina 
WHERE a.Codigo = 2 and fa.CentroCusto <> 2 GROUP BY a.descricao, f.MatriculaSese, f.nome 
HAVING COUNT(DISTINCT tf.CodTreina) = COUNT(CASE WHEN TodosTreinosArea.CodTreina IS NOT NULL THEN TodosTreinosArea.CodTreina END) AND COUNT(DISTINCT tf.CodTreina) = MAX(TodosTreinosArea.numTreinos) ORDER BY 1, 2, 3
  • Cara o in really works this way, it brings any item of the list of IN bata... It is not feasible to do a SELECT * FROM vw_treina_func TF WHERE TF.CodTreina = 1 and TF.CodTreina = 16 and TF.CodTreina = 22 and TF.CodTreina = 33 and TF.CodTreina = 75 and TF.CodTreina = 97110 and TF.CodTreina = 115 and TF.CodTreina = 158 and TF.CodTreina = 161 and TF.CodTreina = 164 and TF.CodTreina = 173

  • thank you, people I am testing all the alternatives this with and I tried the example I reported in this coming from a select , same deal in php making a loop to generate all the and brings no result no record and know that in the reported example is to bring back 30 employees. I made this select directly in the bank and still does not bring result with and.

3 answers

3


You can try something like this:

SELECT CodFuncionario
  FROM vw_treina_func TF 
 WHERE TF.CodTreina IN (1, 16, 22, 33, 75, 97, 110, 115, 158, 161, 164, 173)
GROUP BY CodFuncionario
HAVING COUNT(DISTINCT TF.CodTreina) = 12

The important part is the instruction: HAVING COUNT(DISTINCT TF.Codtreina) = 12 This will limit the results to employees who have 12 different Codtrains.

Edit after @Lucianosilva comment

The aim is to identify which officials have completed all training for the selected area.

As an example I created a small database with some of the tables in your model.

CREATE TABLE area
(
  cod_area  INT,
  descricao NVARCHAR(25)
);

CREATE TABLE treino_area
(
  cod_treina  INT,
  cod_area INT
);

CREATE TABLE funcionario
(
  cod_func  INT,
  nome      NVARCHAR(25)
);

CREATE TABLE treino_func
(
  cod_func   INT,
  cod_treina INT
);

Then I uploaded some test data

INSERT INTO area(cod_area, descricao)VALUES
(1, 'Area A1'),
(2, 'Area B2');

INSERT INTO treina_area(cod_treina, cod_area)VALUES
(1, 1), -- Area A1 treino 1
(2, 1), -- Area A1 treino 2
(2, 2); -- Area B2 treino 2

INSERT INTO funcionario(cod_func, nome)VALUES
(1, 'Jorge'),
(2, 'Manuel'),
(3, 'Pedro');

INSERT INTO treina_func(cod_func, cod_treina)VALUES
(1, 1), -- Jorge treino 1
(1, 2), -- Jorge treino 2
(2, 1), -- Manuel treino 1
(3, 2); -- Pedro treino 2

The following query will return the employees who have completed all training to the "Area A1 area".

SELECT a.cod_area,
       a.descricao,
       f.cod_func,
       f.nome
  FROM area a
 INNER JOIN treina_area ta
    ON ta.cod_area = a.cod_area
 INNER JOIN treina_func tf
    ON tf.cod_treina = ta.cod_treina
 INNER JOIN funcionario f
    ON f.cod_func = tf.cod_func
 LEFT JOIN 
 (
    SELECT cod_area,
           cod_treina,
           (SELECT COUNT(DISTINCT iita.cod_treina) FROM treina_area iita WHERE iita.cod_area = ita.cod_area) numTreinos
      FROM treina_area ita       
 ) TodosTreinosArea
    ON TodosTreinosArea.cod_area = ta.cod_area
   AND TodosTreinosArea.cod_treina = ta.cod_treina
 WHERE a.cod_area = 1
 GROUP BY a.descricao, f.cod_func, f.nome
 HAVING COUNT(DISTINCT tf.cod_treina) = COUNT(CASE WHEN TodosTreinosArea.cod_treina IS NOT NULL THEN TodosTreinosArea.cod_treina END)
    AND COUNT(DISTINCT tf.cod_treina) = MAX(TodosTreinosArea.numTreinos)
 ORDER BY 1, 2, 3

Upshot:

cod_area    descricao   cod_func    nome
1           Area A1     1           Jorge

Only the employee Jorge is returned because he is the only one who has completed all the necessary training: training 1 and training 2. Pedro is not listed because he only completed training 2 - he still has to complete training 1.

The result when the area selected is "Area B2" is as follows, as both Jorge and Pedro completed training 2:

cod_area    descricao   cod_func    nome
2           Area B2     1           Jorge
2           Area B2     3           Pedro 

The Sqlfiddle as an example.

  • IN is the result of a select from the training_area table which has all trainings related to the area and as you select an area code the amount of training will change

  • Thank you very much Bruno I made some changes and it worked. I will edit put the code because I do not know put here in the comment.

2

I suppose there’s an employee table and a training table, right?

It would be something like:

DECLARE @QUANTIDADE_TREINAMENTOS int

SELECT @QUANTIDADE_TREINAMENTOS = count(*) FROM Treina

SELECT DISTINCT
    CodFunc,
    (SELECT count(*) from vw_treina_func TF2 where TF2.CodFunc = vw_treina_func.CodFunc AND TF2.CodTreina = vw_treina_func.CodTreina) as quantidade
FROM
    vw_treina_func TF
WHERE
    quantidade = @QUANTIDADE_TREINAMENTOS

This brings only the view records that have the same amount of training as the number of records in the training table.

  • I’m sorry but in this case it will bring only if the "func" matches all the matches of the table Trains? or if you hit only one it already selects

  • Oops, I made a mistake. I’ll fix it.

  • Okay, now it’s fixed.

  • Face a doubt that perhaps it is pertinent, and if he wants only these codes cited above and not the whole table? would have an easy and compact way to solve it ? or he should put a where giant with several and equal quoted above ?

  • 1

    @Meajudasilvio if you only want the above codes, just apply the "in" clause of the question to select that fills the value of the variable @QUANTIDADE_TREINAMENTOS. Unfortunately this is a case not so common in SQL, I can not think of a solution generic with less code. But for a non-generic solution, the answer from Bruno is the most direct.

0

Hello,

you must have a table with the trainings then it would be:

To take the total amount of materials

declare @qtdTreinamento bigint

SELECT qtdTreinamento  = (SELECT DISTINCT CodTreina FROM ***TREINAMENTO*** WHERE CodTreina IN (1,16,22,33,75,97110, 115, 158,161,164,173))

**Selecionar somente os que têm o total informado**

select * from **vw_treina_func**  where Matricula in (select matricula from vw_treina_func group by matricula having count(*) = @qtdTreinamento)
  • Yes I put the DER to facilitate the understanding I have a table training and one that relates the training to the area that is the training_area. I will test your solution.

Browser other questions tagged

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