I have a table Masterproduct and I want to retrieve only a single row for every 'ProductDivisionID' along with the check whether the 'StatusID' of any row is 2 for a particular 'ProductDivisionID'
If I read your question correctly, you want a list of productDivisionID values for those division where any row has a StatusID of 2. In this case, you could use aggregation over divisions, and count the number of occurrences:
SELECT productDivisionID
FROM Masterproduct
GROUP BY productDivisionID
HAVING SUM(CASE WHEN StatusID = 2 THEN 1 ELSE 0 END) > 0
Or even simpler, just use a WHERE condition to remove records where the StatusID is not 2, and then SELECT DISTINCT to get the list of divisions:
SELECT DISTINCT productDivisionID
FROM Masterproduct
WHERE StatusID = 2
This gives you columns productID as maximum value and StatusID as 2 for each productDivisionID
SELECT productDivisionID, MAX(productID) as productID , MAX(StatusID) As StatusID
FROM Masterproduct
WHERE StatusID = 2
GROUP BY productDivisionID
Related
I am trying to write a query from a table A which has 2 columns :
ID , STATUS
The Status can be PROCESSING, NOTPROCESSED, FAILED, SUCCESS
When a record is successfully processed, a new record is created in the DB with STATUS as PROCESSED and the ID is the same as the previous NOTPROCESSED record.
The Sample Records in DB would like :
1 NOTPROCESSED
2 PROCESSED
1 PROCESSED
3 NOTPROCESSED
4 NOTPROCESSED
2 PROCESSED
3 NOTPROCESSED
4 NOTPROCESSED
The records can appear as duplicate for NOTPROCESSED.
I have to query the records which are NOTPROCESSED i.e
3 NOTPROCESSED
4 NOTPROCESSED
Its getting quite confusing to write the query.
Can anyone help with the logic.
you may use not exists to get this output.
select distinct a.id,a.status
from table a
where a.status='NOTPROCESSED'
and not exists (select null
from table b
where b.id=a.id
and b.status='PROCESSED')
Group by the ids and take only those groups having no record of status PROCESSED
select id
from your_table
group by id
having sum(case when status = 'PROCESSED' then 1 else 0 end) = 0
or get only the ones with only one kind of status
having count(distinct status) = 1
or use alphabetically the highest status
having max(status) = 'NOTPROCESSED'
Here are a couple of options:
select distinct id from A where id not in (
select id from A where status = 'PROCESSED'
);
select distinct id from A natural left join (
select id from A where status = 'PROCESSED'
) as B where B.id is null;
You can use analytical function as follows:
select * from
(select t.*, count(case when status = 'PROCESSED' then 1 end)
over (partition by ID) as cnt
from your_table t) t
where status = 'NOTPROCESSED' and cnt = 0
In below table i'm trying to get the workId along with template Id which doesn't have a specific TaskID. Each workId can have multiple Tasks but they don't necessarily have same set of TasksIDs.
E.g I want to get the workIDS which don't have TaskID T02
which I would get
W03 and W05 as a result
Table name: WorkTaks
I tried to the following query but i didn't get the exact results
select workID from WorkTasks
where TaskID != 'T02'
Use correlated subquery
select distinct workID from WorkTasks a
where not exists
(select 1 from WorkTasks b where a.workID =b.workID and TaskID = 'T02')
One method is aggregation:
select workID
from WorkTasks
group by workID
having sum(case when TaskID = 'T02' then 1 else 0 end) = 0;
The having clause counts the number of rows that match the condition (= 'T02'). The = 0 says there are none.
What is the difference between the two SQL queries below other than Query2 returning an additional field? Are there any possible scenarios where the output of the two queries would be different (other than the additional field in Query2)
Query1:
SELECT Field1, COUNT(*)
FROM Table1
GROUP BY Field1
HAVING COUNT(*) > 1
Query2:
SELECT Field1, Field2, COUNT(*)
FROM Table1
GROUP BY Field1, Field2
HAVING COUNT(*) > 1
Absolutely, these are different. Query2's Group By clause specifies an extra field. That means when the results are aggregated, they will be aggregated for the combined unique values of Field1 AND Field2. That is, two records are aggregated if and only if both Field1 and Field2 are equal.
For example:
SELECT Profession, Count(*)
FROM People
GROUP BY Profession
HAVING Count(*) > 1
will return a list of professions with associated counts like:
Software Developer, 10
PM, 5
Tester, 2
whereas:
SELECT Profession, Gender, Count(*)
FROM People
GROUP BY Profession, Gender
HAVING Count(*) > 1
will return a list of professions broken out by gender like:
Software Developer, Male, 5
Sofware Developer, Female, 5
PM, Male, 3
PM, Female, 2
Tester, Male, 2
Edit with additional requested information:
You can retrieve counts of professions with rows for both genders via:
SELECT Profession, Count(*)
FROM People
GROUP BY Profession
HAVING SUM(case Gender when 'Female' then 1 else 0 end) > 0 AND SUM(case Gender when 'Male' then 1 else 0 end) > 0
It gets a bit hairy (need subqueries) if you also need associated gender counts
Extra group by clause in query 2 filters records.To know more look at below example.
test data:
id name
1 a
2 b
3 a
4 a
So when I say group by name,sql first filters out distinct records for name which goes like below for the below query
select name,sum(id)
from test
group by name
--first filter out distinct values for group by column (here name)
a
b
--next for each distinct record ,how many values fall into that category..
a 1 a
4 a
3 a
b 2 b
So from the above groups ,now you can calculate any aggregations on the group in our case,it is sum,so next output will go some thing like this
a 8
b 2
As you can see from above output,you also can calculate,any aggregation on group (here a and b values) ,like give me count(id),len(name) on group like below
select name,len(name),sum(id)
from test
group by name
The same thing happens when you group by another field,lets say like below
select id,name
from
test
group by id,name
so in above case,sql first filters alldistinct records for id,name
1 a
2 b
3 a
4 a
next step is to get records which fall for each group
groupby columns --columns which fall into this
1 a 1 a
2 b 2 b
3 a 3 a
4 a 4 a
Now you can calculate aggergations on above groups.hope this helps in visualizing your group by.further having will eliminate groups after group by phase,where will eliminate record before group by phase
Using SQL Server, I have a table as shown in the sample table below. I need to have sum of all the unique values per the columns "BookOrder, StationaryOrder, and Printing Order".
SAMPLE TABLE:
KeyIDCustomer BooksOrder StationaryOrder PrintingOrder
29945843 1070756 1891514 198876
29945843 1070756 1893827 198876
29945843 1070758 1891514 198876
29945843 1070758 1893827 198876
I am using the below coding to achieve this goal.
Select DISTINCT KeyIDCustomerID,
Sum(Case when BooksOrder is not null then 1 else 0 End) TotalBookOrders,
Sum(Case when StationaryOrder is not null then 1 else 0 End) TotalStationaryOrder,
Sum(Case when PrintingOrder is not null then 1 else 0 End)TotalPrintingOrder
With this coding in am getting the results as below
KeyIDCustomerID TotalBookOrders TotalStationaryOrder TotalPrintingOrder
29945843 4 4 4
I expect the results to be like this
KeyIDCustomerID TotalBookOrders TotalStationaryOrder TotalPrintingOrder
29945843 2 2 1
Is there a way i can accomplish this Goal in SQL?
Thanks
i think the proper term for
sum of all the unique values per the columns
is "count of unique values"
COUNT (DISTINCT column_name) returns the number of unique, non-null values in column_name
Select
KeyIDCustomerID,
COUNT(DISTINCT BooksOrder) as TotalBookOrders,
COUNT(DISTINCT StationaryOrder) as TotalStationaryOrder,
COUNT(DISTINCT PrintingOrder) as TotalPrintingOrder
FROM SAMPLE_TABLE
GROUP BY KeyIDCustomerID
Do a group by, count(distinct column) to count:
Select KeyIDCustomerID,
COUNT(distinct BooksOrder) TotalBookOrders,
COUNT(distinct StationaryOrder) TotalStationaryOrder,
COUNT(distinct PrintingOrder) TotalPrintingOrder
from tablename
group by KeyIDCustomerID
Simplified for example, I have two tables, groups and items.
items (
id,
groupId,
title
)
groups (
id,
groupTitle,
externalURL
)
The regular query I'm goes something like this:
SELECT
i.`id`,
i.`title`,
g.`id` as 'groupId',
g.`groupTitle`,
g.`externalURL`
FROM
items i INNER JOIN groups g ON (i.`groupId` = g.`id`)
However I need to modify this now, because all the groups which specify an externalURL will not have any corresponding records in the items table (since they're stored externally). Is it possible to do some sort of join so that the output looks kinda like this:
items:
id title groupId
----------------------
1 Item 1 1
2 Item 2 1
groups
id groupTitle externalURL
-------------------------------
1 Group 1 NULL
2 Group 2 something
3 Group 3 NULL
Query output:
id title groupId groupTitle externalURL
---------------------------------------------------
1 Item 1 1 Group 1 NULL
2 Item 2 1 Group 1 NULL
NULL NULL 2 Group 2 something
-- note that group 3 didn't show up because it had no items OR externalURL
Is that possible in one SQL query?
This is exactly what an outer join is for: return all the rows from one table, whether or not there is a matching row in the other table. In those cases, return NULL for all the columns of the other table.
The other condition you can take care of in the WHERE clause.
SELECT
i.`id`,
i.`title`,
g.`id` as 'groupId',
g.`groupTitle`,
g.`externalURL`
FROM
items i RIGHT OUTER JOIN groups g ON (i.`groupId` = g.`id`)
WHERE i.`id` IS NOT NULL OR g.`externalURL` IS NOT NULL;
Only if both i.id and g.externalURL are NULL, then the whole row of the joined result set should be excluded.