i have two tables join to show the count value of first table and i write a query like this
i have a table that contain category called [PEBPC] that contain a 3 producer category
USE [P1OTP]
SELECT pe.[ID] AS [No]
,pe.[NAME] AS [ProducerType]
,coalesce(COUNT(CASE tp.[NewProducer] WHEN 0 THEN 1 ELSE NULL END),0) AS [NewProducers]
,coalesce(COUNT(CASE tp.[NewProducer] WHEN 1 THEN 1 ELSE NULL END),0) AS [ExistProducer]
,coalesce(COUNT(tp.[NewProducer]),0) AS [Total]
FROM [TPDCS]
LEFT JOIN [PEBPC] pe ON pe.[ID] = tp.[estbProducerID]
WHERE 1 = 1
AND tp.[OrganizationAddrProvince] IS NOT NULL
AND tp.[OrganizationAddrProvince] = '81'
AND tp.[libDocumentID] IN(SELECT [ParentID] FROM [TPDTS] WHERE [CategoryID] IS NOT NULL) >
GROUP BY pe.[ID]
,pe.[NAME] ORDER BY pe.[ID]
when this query run it's only show just 2 category because this province have just 1 and 2 category
No Type of Producer NewProducer ExistProducer Total
1 Citizen Producer 102 0 102
2 sole proprietorship 45 0 45
i tried coalesce, count or something that can return 0 but it's doesn't work
i need them to return like this
No Type of Producer NewProducer ExistProducer Total
1 Citizen Producer 102 0 102
2 sole proprietorship 45 0 45
3 SME Producer 0 0 0
How about this? Use PEBPC as your main table and left join it to TPDCS. Note that I move all your WHERE conditions in the JOIN part:
SELECT
pe.[ID] AS [No]
,pe.[NAME] AS [ProducerType]
,COALESCE(COUNT(CASE tp.[NewProducer] WHEN 0 THEN 1 ELSE NULL END),0) AS [NewProducers]
,COALESCE(COUNT(CASE tp.[NewProducer] WHEN 1 THEN 1 ELSE NULL END),0) AS [ExistProducer]
,COALESCE(COUNT(tp.[NewProducer]),0) AS [Total]
FROM [PEBPC] pe
LEFT JOIN [TPDCS] tp ON pe.[ID] = tp.[estbProducerID]
AND tp.[OrganizationAddrProvince] IS NOT NULL
AND tp.[OrganizationAddrProvince] = '81'
AND tp.[libDocumentID] IN(SELECT [ParentID] FROM [TPDTS] WHERE [CategoryID] IS NOT NULL)
GROUP BY pe.[ID], pe.[NAME]
ORDER BY pe.[ID]
Related
i have 2 tables like below:
lk_premier:
code descr
P Premier
N Non Premier
Case:
id taxPin
1 123
2 789
Status:
id voting_status premier
1 5 P
1 5 P
1 5 P
2 5 P
2 5 N
2 5 null
3 5 null
3 5 null
3 5 null
3 5 null
3 5 null
I used the below sql
select
decode(premier,
'P',
'PREMIER',
'N',
'NON PREMIER') as caseStatus,
count(*) as count
from
status s,
case c
where
c.id = s.id
and c.id = 1
and s.voting_status = 5
group by
premier
I want to join the lk_premier table, so my output looks like for id=2,
caseStatus count
PREMIER 1
NON PREMIER 1
for id = 3
caseStatus count
PREMIER 0
NON PREMIER 0
You should never do joins this way -- this way of doing joins was depreciated about 20 years ago. the join should look like this:
join status s on c.id = s.id
once you do joins the right way then how you do left joins is easier as seen below:
here you go
select
coalesce(p.desc,'unknown') as caseStatus,
count(*) as count
from case c
join status s on c.id = s.id
left join lk_premier p on p.code = c.premier
where c.id = 1 and s.voting_status = 5
group by coalesce(p.desc,'unknown')
I have two tables that look like this:
sMinMax:
PartNo baseID Min Max
11795 1 1 1
11795 5 0 0
11795 6 1 1
01655 65 2 3
vsStock:
PartNo baseID Qty
11795 1 1
11795 1 1
11795 55 1
I would like to join them so I get a table that shows all the columns together for all the parNo en bases like this:
result:
PartNo baseID Min Max Qty
11795 1 1 1 2
11795 5 0 0 null
11795 6 1 1 null
11795 55 null null 1
01655 65 2 3 null
So I would just do this with a full outer join on two columns but this gives the same results that I would expect from a left join. I tried 1000 things but this is my last try:
SELECT
a.sPart_ID
,a.uRALBase_ID
,a.MinQty
,a.MaxQty
,b.Qty
FROM [RALNHVTST].[dbo].[sMinMax] as a
FULL OUTER JOIN [RALNHVTST].[dbo].[vsStockList] as b
ON a.sPart_ID = b.sPart_ID
AND a.uRALBase_ID = b.uRALBase_ID
WHERE a.sPart_ID IS NOT NULL
AND a.sPart_ID = 1159
ORDER BY a.sPart_ID
but as I said this gives me the same results as a LEFT JOIN. Anyone have an idea what I'm doing wrong?
Something like that? This query gives me same result as you expected.
SELECT
CASE WHEN a.PartNo IS NOT NULL THEN a.PartNo ELSE b.PartNo END AS PartNo
,CASE WHEN a.baseId IS NOT NULL THEN a.baseId ELSE b.baseId END AS baseId
,a.[Min]
,a.[Max]
,SUM(b.Qty) AS Qty
FROM [dbo].[sMinMax] as a
FULL JOIN [dbo].[vsStock] as b
ON a.partNo = b.partNo
AND a.baseId = b.baseId
GROUP BY
CASE WHEN a.PartNo IS NOT NULL THEN a.PartNo ELSE b.PartNo END,
CASE WHEN a.baseId IS NOT NULL THEN a.baseId ELSE b.baseId END,
a.[Min],
a.[Max]
ORDER BY
CASE WHEN a.PartNo IS NOT NULL THEN a.PartNo ELSE b.PartNo END
Filtering in a full join is tricky. I would recommend filtering and aggregating in subqueries:
SELECT COALESCE(sm.sPart_ID, s.sPart_Id) as sPartId,
COALESCE(sm.uRALBase_ID, sm.uRALBase_ID
sm.MinQty, sm.MaxQty, s.Qty
FROM (SELECT sm.*
FROM [RALNHVTST].[dbo].[sMinMax] sm
WHERE sm.sPart_ID = 1159
) sm FULL OUTER JOIN
(SELECT s.sPart_ID, s.uRALBase_ID, SUM(qty) as qty
FROM [RALNHVTST].[dbo].[vsStockList] s
WHERE s.sPart_ID = 1159
GROUP BY s.sPart_ID, s.uRALBase_ID
) s
ON sm.sPart_ID = s.sPart_ID AND
sm.uRALBase_ID = s.uRALBase_ID
ORDER BY sPart_ID
What will be the query for fetching all the records from left table and matching records from the right tables?
Tables:
properties:
id cid property_name
1 1 Property1
2 1 Property2
3 1 Property3
4 1 Property4
property_medias:
id cid property_id media_file_id
1 1 1 1
2 1 1 2
3 1 1 4
4 1 2 5
5 1 2 6
media_files
id cid media_alt
1 1 NULL
2 1 pqr
3 1 NULL
4 1 ttt
5 1 NULL
6 1 NULL
Expected Output:
id cid property_name media_alt
1 1 Property1 YES
2 1 Property2 NO
3 1 Property3 -
4 1 Property4 -
Explanation of output:
Property1 is having atleast one record having media_alt IS NOT NULL hence media_alt is 'YES'
Property2 is having all the records NULL for media_alt hence media_alt is 'NO'
Property3 and Property4 are not having any media associated with it hence media_alt is '-'.
I tried with this query but it is giving me duplicate records of properties.
SELECT distinct p.id, p.property_name, mf.media_alt
FROM
properties AS p
JOIN property_medias pm ON ( pm.property_id = p.id AND pm.cid = p.cid)
JOIN media_files mf ON ( mf.id = pm.media_file_id AND mf.cid = pm.cid )
WHERE
p.cid = 1
ORDER BY p.property_name
Please help me in the right direction.
You are describing a LEFT JOIN and GROUP BY:
SELECT p.id, p.property_name,
(CASE WHEN COUNT(mf.media_alt) > 0 THEN 'YES'
WHEN COUNT(mf.cid) > 0 THEN 'NO'
ELSE '-'
END) as media_alt
FROM properties p LEFT JOIN
property_medias pm
ON pm.property_id = p.id AND pm.cid = p.cid LEFT JOIN
media_files mf
ON mf.id = pm.media_file_id AND mf.cid = pm.cid
WHERE p.cid = 1
GROUP BY p.id, p.property_name;
The first COUNT() is determining if any of the column values are not NULL. The second is determining if there are any matches.
You could also phrase this using EXISTS:
SELECT p.id, p.property_name,
(CASE WHEN EXISTS (SELECT 1
FROM property_medias pm LEFT JOIN
media_files mf
ON mf.id = pm.media_file_id AND mf.cid = pm.cid
WHERE pm.property_id = p.id AND
pm.cid = p.cid AND
mf.media_alt IS NOT NULL
)
THEN 'YES'
WHEN EXISTS (SELECT 1
FROM property_medias pm
WHERE pm.property_id = p.id AND
pm.cid = p.cid
)
THEN 'NO'
ELSE '-'
END) as media_alt
FROM properties p
WHERE p.cid = 1;
This saves the outer aggregation, but may not have any performance advantage in Postgres.
In a document review tool, one can create "batches" of documents. A batch is a group of related documents, identified by GroupID.
These groups of documents are presented to reviewers, who update a field called Testcompleted. This field has 3 possible states: 1, 0 or null. The number of documents in a group varies.
In the example below I have 3 groups ("batches") of documents. The first batch (batch_0001), for instance, has 2 documents (58 and 59).
#Document
ArtifactID Testcompleted GroupID
--------------------------------------
58 1 4
59 1 4
60 null 6
61 1 6
62 null 7
63 null 7
64 null 7
#DocumentBatch
BatchArtifactID DocumentArtifactID
-------------------------------------
66 58
66 59
67 60
67 61
68 62
68 63
68 64
#Batch
ArtifactID Name
------------------------
66 batch_0001
67 batch_0002
68 batch_0003
I need to know when a batch is completed -- that is: when all documents in that batch have the Testcompleted field set to 1. In the example, this is the case for batch_0001.
The output I am looking for is:
batch documents reviewed completed
------------------------------------------------------
batch_0001 2 2 yes
batch_0002 2 1 no
batch_0003 3 0 no
I started by joining the tables:
select
*
from
#Document d
left join #DocumentBatch db
on db.DocumentArtifactID = b.ArtifactID
left join #Batch b
on db.BatchArtifactID = b.ArtifactID
where
d.Testcompleted = 1
;
This obviously does not return the result I need, but I am stuck. Some help on how to solve this would be greatly appreciated.
select
b.name,
count(db.DocumentArtifactID) as documents,
-- count only completed
count(case when d.Testcompleted = 1 then d.ArtifactID end) as reviewed,
-- if the minimum = 1 there's no 0 or NULL
case when min(cast(Testcompleted as tinyint)) = 1 then 'yes' else 'no' end as completed
from
#Batch b
left join #DocumentBatch db
on db.BatchArtifactID = b.ArtifactID
left join #Document d
on db.DocumentArtifactID = d.ArtifactID
group by b.name;
If there are no missing rows you can switch to Inner Joins...
What you want is aggregation,so you need a group by. Something like this:
select b.name as batchname, count(d.ARtifactID) as numdocuments,
sum(case when d.testCompleted = 1 then 1 else 0 end) as NumCompleted,
(case when sum(case when d.testCompleted = 1 then 0 else 1 end) > 0
then 'No'
else 'Yes'
end) as AllCompleted
from #Batch b left join
#DocumentBatch db
on db.BatchArtifactID = b.ArtifactID
#Document d left join
on db.DocumentArtifactID = b.ArtifactID left join
group by b.name;
I don't think outer joins are needed. You should be able to use inner join, unless there are batches with no documents. If you do use outer joins, starting with #Batch makes more sense than #Document, because you are aggregating at the batch level.
You can try something like this:
select b.name
, count(*) as documents
, sum(d.Testcompleted) as reviewed
, (case when count(*) = sum(d.Testcompleted) then 'yes' else 'no' end) as completed
from [#Document] d
join [#DocumentBatch] db on db.DocumentArtifactID = d.ArtifactID
join [#Batch] b on db.BatchArtifactID = b.ArtifactID
group by b.name
SQLFiddle
count(*) includes into calculation all values;
sum(d.Testcompleted) count only cases where Testcompleted is 1;
I have the following table, Persons_Companies, that shows a relation between persons and companies knowns by these persons:
PersonID | CompanyID
1 1
2 1
2 2
3 2
4 2
Imagining that company 1 = "Google" and company 2 is = "Microsoft", I would like to know the query to have the following result:
PersonID | Microsoft | Google
1 0 1
2 1 1
3 1 0
4 1 0
Until this moment I have something similar:
select PersonID,
case when CompanyID=1 then 1 else 0
end as Google,
case when EmpresaID=2 then 1 else 0
end as Microsoft
from Persons_Companies
My problem is with the persons that knows both companies, I can't imagine how could this query be.
What is the SQL query?
select PersonID,
case when EXISTS (
SELECT 1
FROM Persons_Companies pc1
WHERE pc.PersonID = pc1.PersonID and pc1.CompanyID = 1 ) then 1 else 0
end as Google,
case when EXISTS (
SELECT 1
FROM Persons_Companies pc2
WHERE pc.PersonID = pc2.PersonID and pc2.CompanyID = 2 ) then 1 else 0
end as Microsoft
from Persons_Companies pc
SELECT personId, sum(case companyId when 1 then 1 else 0 end) google,
sum(case companyId when 2 then 1 else 0 end) microsoft
from Persons_Companies
group by personId
order by personId;
I think this is what you want: http://pastie.org/881092
select
p.person_id,
if(ms.company_id is null,0,1) as 'microsoft',
if(ora.company_id is null,0,1) as 'oracle',
if(mysql.company_id is null,0,1) as 'mysql'
from
person p
left outer join person_company ms on p.person_id = ms.person_id and ms.company_id = 1
left outer join person_company ora on p.person_id = ora.person_id and ora.company_id = 2
left outer join person_company mysql on p.person_id = mysql.person_id and mysql.company_id = 3
order by
p.person_id;
There is a problem with both answers, because there is an assumption that Google and Microsoft will always be the only companies on the table. I believe the query should be generic.
I am not too sure but I think a combination of a cross tab and CTE will work well.