SQL tricky query - sql

I have this query
select lab.IDLAB,
lab.NOMLAB,
lab.CAPACIDAD
from laboratorio lab
inner join DETALLESOLICITUD det on det.IDLAB = lab.IDLAB
inner join dia on dia.iddia = det.iddia
inner join bloque blo on blo.idbloque = det.idbloque
inner join solicitud sol on sol.IDSOLICITUD=det.IDSOLICITUD
where blo.idbloque = 1
and dia.iddia = 1
and sol.estado in (1,2)
which returns:
IDLAB | NOMLAB | CAPACIDAD
----------------------------
1 | LCOMP1 | 22
And it does exactly what I want it to do. Now I want to get all the records from the table laboratorios that doesn't appear in this query. For example my laboratorios table has contents:
IDLAB | NOMLAB | CAPACIDAD
----------------------------
1 | LCOMP1 | 22
2 | LCOMP2 | 31
3 | LCOMP3 | 17
4 | LCOMP4 | 26
And I want the following output:
IDLAB | NOMLAB | CAPACIDAD
----------------------------
2 | LCOMP2 | 31
3 | LCOMP3 | 17
4 | LCOMP4 | 26
I tried with a not exists statement this way:
select *
from laboratorio
where not exists(
select lab.idlab, lab.nomlab, lab.CAPACIDAD
from laboratorio lab
inner join DETALLESOLICITUD det on det.idlab = lab.idlab
inner join dia on dia.iddia = det.iddia
inner join bloque blo on blo.idbloque = det.idbloque
inner join solicitud sol on sol.IDSOLICITUD = det.IDSOLICITUD
where blo.idbloque = 1
and dia.iddia = 1
and sol.estado in(1,2)
);
and this way:
select *
from laboratorio
where not exists(
select det.IDLAB
from DETALLESOLICITUD det
inner join dia on dia.iddia = det.iddia
inner join bloque blo on blo.idbloque = det.idbloque
inner join solicitud sol on sol.IDSOLICITUD = det.IDSOLICITUD
where blo.idbloque = 1
and dia.iddia = 1
and sol.estado in(1,2)
);
but both returns nothing. Any help will be really appreciate.

Your sub-queries return rows. You know that because of the first query. But where not exists is only true when the sub-query returns no rows. Check it out:
SQL> select * from dual
2 /
D
-
X
SQL> select * from dual
2 where not exists (select * from dual
3 where dummy = 'X')
4 /
no rows selected
SQL> select * from dual
2 where not exists (select * from dual
3 where dummy = 'Y')
4 /
D
-
X
SQL>
So what you need to do is correlate the outer query with the sub-query. Easiest way to do this:
select * from laboratorio
where (idlab, nomlab, CAPACIDAD)
not in (select lab.idlab, lab.nomlab, lab.CAPACIDAD
from laboratorio lab
inner join DETALLESOLICITUD det on det.idlab = lab.idlab
inner join dia on dia.iddia = det.iddia
inner join bloque blo on blo.idbloque = det.idbloque
inner join solicitud sol on sol.IDSOLICITUD=det.IDSOLICITUD
where blo.idbloque = 1
and dia.iddia = 1
and sol.estado in(1,2)
)

select * from laboratorio lab1 WHERE NOT EXISTS (
select 1 from laboratorio lab
inner join DETALLESOLICITUD det on det.IDLAB = lab.IDLAB
inner join dia on dia.iddia = det.iddia inner join bloque blo on blo.idbloque = det.idbloque
inner join solicitud sol on sol.IDSOLICITUD=det.IDSOLICITUD
where blo.idbloque = 1 and dia.iddia = 1 and sol.estado in (1,2)
AND lab1.rowid = lab.rowid)
Check this out. I think you did not join with the outer table.

Related

how to generate a report in sql server from a previous select

Periodically I need to generate a report based on some data from database.
The first select IS:
SELECT DISTINCT
A.PRO_C_NOME,
B.ETS_C_NOME
FROM WETI_ETAPA_ITEM F
INNER JOIN WETE_ETAPA_ITEM_EDITORS E
ON E.ETE_N_ETI_N_CODIGO = F.ETI_N_CODIGO
INNER JOIN WETA_ETAPA_PROCESSO H
ON H.ETA_N_CODIGO = F.ETI_N_ETA_N_CODIGO
INNER JOIN WIPR_ITEM_PROCESSO C
ON C.IPR_N_CODIGO = F.ETI_N_IPR_N_CODIGO
INNER JOIN WIWF_ITEM_WORKFLOW D
ON D.IWF_N_CODIGO = C.IPR_N_IWF_N_CODIGO
INNER JOIN WPRO_PROCESSO A
ON A.PRO_N_CODIGO = C.IPR_N_PRO_N_CODIGO AND PRO_N_DELETED = 0
LEFT OUTER JOIN WISP_ITEM_SUBPROCESS G
ON G.ISP_N_ID = F.ETI_ISP_N_ID
INNER JOIN WETS_ETAPA_SLA B
ON F.ETI_N_ETS_N_CODIGO = B.ETS_N_CODIGO
Returns something like this:
C1
C2
A
1
A
1
A
3
B
2
B
2
B
2
B
3
B
3
B
3
C
1
C
2
I need a report from that first select returning something like this:
S.1
S.2
S.3
S.4
A
2
0
1
B
0
3
3
C
1
1
0
that is:
S.1 - distinct values from C1
S.2 - count 1 values in C2 for the S.1 value
S.3 - count 2 values in C2 for the S.1 value
S.4 - count 3 values in C2 for the S.1 value
Can someone help how do I solve this?
I tried many solutions, such as using temporary tables and selecting from another select but doesn't work at all for different reasons.
;with cte(PRO_C_NOME, ETS_C_NOME) as (
SELECT DISTINCT
A.PRO_C_NOME,
B.ETS_C_NOME
FROM WETI_ETAPA_ITEM F
INNER JOIN WETE_ETAPA_ITEM_EDITORS E
ON E.ETE_N_ETI_N_CODIGO = F.ETI_N_CODIGO
INNER JOIN WETA_ETAPA_PROCESSO H
ON H.ETA_N_CODIGO = F.ETI_N_ETA_N_CODIGO
INNER JOIN WIPR_ITEM_PROCESSO C
ON C.IPR_N_CODIGO = F.ETI_N_IPR_N_CODIGO
INNER JOIN WIWF_ITEM_WORKFLOW D
ON D.IWF_N_CODIGO = C.IPR_N_IWF_N_CODIGO
INNER JOIN WPRO_PROCESSO A
ON A.PRO_N_CODIGO = C.IPR_N_PRO_N_CODIGO AND PRO_N_DELETED = 0
LEFT OUTER JOIN WISP_ITEM_SUBPROCESS G
ON G.ISP_N_ID = F.ETI_ISP_N_ID
INNER JOIN WETS_ETAPA_SLA B
ON F.ETI_N_ETS_N_CODIGO = B.ETS_N_CODIGO
)
SELECT PRO_C_NOME AS 'S.1'
,SUM(CASE WHEN ETS_C_NOME=1 THEN 1 ELSE 0 END) AS 'S.2'
,SUM(CASE WHEN ETS_C_NOME=2 THEN 1 ELSE 0 END) AS 'S.3'
,SUM(CASE WHEN ETS_C_NOME=3 THEN 1 ELSE 0 END) AS 'S.4'
FROM cte
GROUP BY PRO_C_NOME

How to join with two tables simultaneously?

Table Product
Id name t1 t2
1 A 1 4
2 B 5 2
3 C 3 1
4 D 4 5
Table Tan
id tan
1 tanA
2 tanB
3 tanC
4 tanD
5 tanE
I have two above table and i want the result as below in expecting result how it is possible.
Expecting result
A tanA tanD
B tanE tanB
C tanC tanA
D tanD tanE
You can join on multiple tables:
SELECT p.Name AS ProductName,
t1.tan AS Tan1,
t2.tan AS Tan2
FROM dbo.Product p
INNER JOIN Tan t1
ON p.t1 = t1.id
INNER JOIN Tan t2
ON p.t2 = t2.id
ORDER BY ProductName ASC
Demo
You can select from the tan table twice by using a table alias:
FROM Product INNER JOIN tan tan1 ON tan1.id = product.t1
INNER JOIN tan tan2 ON tan2.id = product.t2
select the appropriate columns:
SELECT Product.name AS name, tan1.tan AS Tan_1, tan2.tan AS Tan_2
to give:
SELECT product.name AS name, tan1.tan AS Tan_1, tan2.tan AS Tan_2
FROM Product INNER JOIN tan tan1 ON tan1.id = product.t1
INNER JOIN tan tan2 ON tan2.id = product.t2

Count string values From row using sql?

I have a SQL query in which I am using INNER JOIN but I have to calculate the string values ERROR, OK and their total from column d.sd_figure.
This is my SQL query
SELECT
count(d.sd_figure = 'ERROR') AS error,
count(d.sd_figure = 'OK') AS OK count,
count(*) AS total,
m.contr_num, bu.buyer_name,
m.S_remarks, cr.contr_name, br.brand_name,
m.S_date, c.colour_name, s.size_name,
mn.manu_name
FROM
Scanning_M m
INNER JOIN
colour c ON m.color_id = c.colour_id
INNER JOIN
Buyer bu ON m.buyer_id = bu.Byer_ID
INNER JOIN
Scanning_D d ON m.S_id = d.S_id
INNER JOIN
Brand br ON m.Brand_id = br.Brand_id
INNER JOIN
Contract cr ON m.Contr_num = cr.Contr_id
INNER JOIN
Size s ON m.Size_id = s.Size_id
INNER JOIN
Manufacturer mn ON m.Manu_id = mn.manu_id
WHERE
m.S_date BETWEEN '2016-01-13' AND '2016-01-13'
I also want to add count of 'error' , 'OK' and 'Total' too error is in this line
SELECT
count(d.sd_figure = 'ERROR') AS error,
count(d.sd_figure = 'OK') as OK count,
count(*) as total ,
I tried many solution butt returned group by not found etc
SAMPLE DATA DEMANDED FOR d.sd_figure
S_id sd_res sd_figure sd_datetime sd_id
4 456456 ERROR 2016-01-09 03:11:07.000 1
4 456456 ERROR 2016-01-09 03:11:07.000 2
4 456456 ERROR 2016-01-09 03:11:07.000 3
6 123 ERROR 2016-01-09 10:54:47.000 22
6 123 ERROR 2016-01-09 10:54:47.000 23
6 123 ERROR 2016-01-09 10:54:47.000 24
6 123 ERROR 2016-01-09 10:54:48.000 25
6 123 ERROR 2016-01-09 10:54:48.000 26
Untested, but should be something like this:
SELECT sum(CASE WHEN d.sd_figure = 'ERROR' THEN 1 ELSE 0 END) AS error
,sum(CASE WHEN d.sd_figure = 'OK' THEN 1 ELSE 0 END) AS [OK count]
,count(*) AS total
,m.contr_num
,bu.buyer_name
,m.S_remarks
,cr.contr_name
,br.brand_name
,m.S_date
,c.colour_name
,s.size_name
,mn.manu_name
FROM Scanning_M m
INNER JOIN colour c ON m.color_id = c.colour_id
INNER JOIN Buyer bu ON m.buyer_id = bu.Byer_ID
INNER JOIN Scanning_D d ON m.S_id = d.S_id
INNER JOIN Brand br ON m.Brand_id = br.Brand_id
INNER JOIN Contract cr ON m.Contr_num = cr.Contr_id
INNER JOIN Size s ON m.Size_id = s.Size_id
INNER JOIN Manufacturer mn ON m.Manu_id = mn.manu_id
WHERE m.S_date BETWEEN '2016-01-13' AND '2016-01-13'
GROUP BY m.contr_num
,bu.buyer_name
,m.S_remarks
,cr.contr_name
,br.brand_name
,m.S_date
,c.colour_name
,s.size_name
,mn.manu_name

Inner join - more than one table

I'm trying to write a code that will join together information from 3 tables and compare it with a "big table" and according to the comparison update a field in a test table. Look at the example:
Big Table:
Employee_Id status
2322 5
222 3
545 6
4532 2
Table 1:
S_Id status
2322 7
Table 2:
S_Id status
222 3
Table 3:
S_Id status
545 6
4532 3
Test Table:
TE_Id IsNotGood
2322 1
4532 1
222 0
545 0
The id "2322" got 1 because the status in table 1 is not like the status in the big table and same for 4532.
I started writing this:
update Test Table
set isNotGood = 0
with ids as (
select distinct Employee_Id from (
select Employee_Id,Status from BigTable as B
) as T
inner join table1 as W on W.S_ID = T.Employee_Id
inner join table2 as K on K.S_ID = T.Employee_Id
inner join table3 as R on R.S_ID = T.Employee_Id
)
I would be happy for your tips to finish this query.
Thank you very much!
You won't be able to use an inner join unless the employee_id is in all the tables.
UPDATE Test
SET isNotGood = 1
WHERE te_id in (select employee_id
from [Big Table] bt
left join table1 as W on W.s_id = bt.employee_Id
left join table2 as K on K.s_id = bt.employee_Id
left join table3 as R on R.s_id = bt.employee_Id
where (bt.status <> W.status and W.status is not null) or (bt.status <> K.status and k.status is not null) or (bt.status <> R.status and R.status is not null);

ms access max count

Here is my query:
SELECT Count(*) AS CountOfJoker, tblPrediction.GameID
FROM (tblUser INNER JOIN (tblPool INNER JOIN tblUserPool ON tblPool.PoolID = tblUserPool.PoolID) ON tblUser.UserID = tblUserPool.UserID) INNER JOIN (tblResult INNER JOIN tblPrediction ON tblResult.GameID = tblPrediction.GameID) ON tblUser.UserID = tblPrediction.UserID
GROUP BY tblPrediction.GameID, tblPrediction.Joker, tblResult.GroupName, tblPool.PoolID
HAVING (((tblPrediction.Joker)=True) AND ((tblResult.GroupName)='A') AND ((tblPool.PoolID)=314));
Here is the output:
CountOfJoker GameID
2 1
2 2
2 9
1 10
1 17
3 18
I would like the MAX of CountOfJoker with the following output:
CountOfJoker GameID
3 18
Thanks
Drew
You could use select top and order by ... desc
SELECT TOP 1 Count(*) AS CountOfJoker, tblPrediction.GameID
FROM (tblUser INNER JOIN (tblPool INNER JOIN tblUserPool ON tblPool.PoolID = tblUserPool.PoolID) ON tblUser.UserID = tblUserPool.UserID) INNER JOIN (tblResult INNER JOIN tblPrediction ON tblResult.GameID = tblPrediction.GameID) ON tblUser.UserID = tblPrediction.UserID
GROUP BY tblPrediction.GameID, tblPrediction.Joker, tblResult.GroupName, tblPool.PoolID
HAVING (((tblPrediction.Joker)=True) AND ((tblResult.GroupName)='A') AND ((tblPool.PoolID)=314));
ORDER BY Count(*) DESC