I have the below table. I would like to count all unique Ids and then divide by a count where Role is Teacher.
Table A
ID Userid Role
1 A Teacher
2 b Teacher
3 c Student
Something like below.
count(distinct id) / count(distinct id) When Role = Teacher
You can use a simple COUNT DISTINCT with an aggregated CASE expression. I've converted to float so that the result returns decimals but you will want to check out your data types before applying to your system.
Temp Table for sample data
CREATE TABLE #TestData (ID float, Userid nvarchar(1), Role nvarchar(7))
INSERT INTO #TestData
VALUES
(1,'A','Teacher')
,(2,'B','Teacher')
,(3,'C','Student')
Query
SELECT
COUNT(distinct td.ID) DistinctID
,SUM(CASE WHEN td.Role = 'Teacher' THEN 1 ELSE 0 END) Teachers
,CONVERT(float,COUNT(distinct td.ID)) / CONVERT(float,SUM(CASE WHEN td.Role = 'Teacher' THEN 1 ELSE 0 END)) FinalField
FROM #TestData td
Result
DistinctID Teachers FinalField
3 2 1.5
Related
I hope i word this out in a way that makes sense;
I'm trying to do a basic select statement for a list of companyIDs. The arguments in questions are options regarding invoices. We have multiple invoice types and they can either be set to be sent by E-mail or be printed. They can be mixed as in some e-mail, some printed, some have nothing selected. There's a total of 9 unique invoice types that i need to check for each company ID.
I'm trying to select distinct company IDs(cmp_id) where the print AND e-mail options are all N or NULL for every single invoicetype. Both options have to be off for both print and e-mail for all invoice types ( In the table i'm selecting from, there's 9 records for the same companyID for each invoicetype)
Some examples ( I'm only using 3 invoice types for the example):
Cmp_id invoiceType print e-mail
company1 credit Y N
company1 supplemental Y N
company1 misc Y Y
company2 supplemental N N
company2 misc N N
The results should be a single column for cmp_id; In the example it would only be company2.
Just perfrom a coditional COUNT to check how many 'Y' you have.
Im assuming print and e-mail only have 3 states, Y, N or NULL
SELECT Cmp_id
FROM YourTable
GROUP BY Cmp_id
HAVING COUNT(CASE WHEN print = 'Y' or e-mail = 'Y' THEN 1 END) = 0
So if count is 0 mean all values are NULL or N
Working DEMO
SELECT DISTINCT Cmp_ID
FROM dbo.table
WHERE
COALESCE([Print], 'N') = 'N'
AND
COALESCE([E-Mail], 'N') = 'N'
Use coalesce to catch the NULLs and Ns.
Would this work:
SELECT DISTINCT Cmp_ID from dbo.table where (Print = 'N') AND (E-Mail = 'N') OR
(Print IS NULL) AND (E-Mail IS NULL)
SELECT T1.Cmp_id, COUNT(*)
FROM dbo.table T1
WHERE
COALESCE([Print], 'N') = 'N'
AND
COALESCE([E-Mail], 'N') = 'N'
GROUP BY T1.Cmp_id
HAVING COUNT(T1.Cmp_id) = (SELECT COUNT(1) FROM dbo.table WHERE Cmp_id = T1.Comp_Id)
Count where both options are either NULL or N and that count = the count of Cmp_Ids in the table.
Assumption:
each [Cmp_ID] has n rows in the table where n is the number of [invoiceTypes]
Sample Data:
CREATE TABLE #temp ([Cmp_id] VARCHAR(20), [invoiceType] VARCHAR(20), [print] VARCHAR(20), [e-mail] VARCHAR(20), )
INSERT INTO #temp
VALUES
('company1','credit','Y','N'),
('company1','supplemental','Y','N'),
('company1','misc','Y','Y'),
('company2','credit','N','N'),
('company2','supplemental','N','N'),
('company2','misc','N','N')
Query using Common table Expression, GROUP BY and HAVING:
We assign the value 1 for every row that has [Print], and [e-mail] as NULL or 'N'. Then we only retrieve the [Cmp_id] of the company that has all its invoiceType with [Print], and [e-mail] as NULL or 'N'.
;WITH CTE AS ( SELECT [Cmp_id],
[NoneSelected] = CASE WHEN ISNULL([print],'N') = 'N' AND ISNULL([e-mail],'N') ='N' THEN 1 ELSE 0 END
FROM #temp )
SELECT Cmp_id
FROM CTE
GROUP BY Cmp_id
HAVING SUM(NoneSelected) = 3 --<-- change this to 9 for 9 invoice types
Results:
Try using Temp tables in response to the comment "We're on compatibility 80, i've tried using CTEs before but they didn't work :S Thanks forthe input though.":
IF OBJECT_ID('tempdb..#temp2') IS NOT NULL
DROP TABLE #temp2;
SELECT [Cmp_id],
[NoneSelected] = CASE WHEN ISNULL([print],'N') = 'N' AND ISNULL([e-mail],'N') ='N' THEN 1 ELSE 0 END INTO #temp2
FROM #temp
SELECT Cmp_id
FROM #temp2
GROUP BY Cmp_id
HAVING SUM(NoneSelected) = 3 --<-- change this to 9 for 9 invoice types
I have a table which has three column - An Id, a foreign key and Status. I need to find the no of active(value = 1) status in the table and the total rows in the table. How to do it in a single query.
Output of this query is Joined With another Table.
select FK, Count(1) as active_count, <missing> as total_count from table where status = 1;
Try
select
FK,
count(1) total_count,
sum(case when status = 1 then 1 else 0 end) active_count
from table
--group by FK
So, I have a table with which individuals (person_id) have multiple lines (up to 4) and values for a column (value_column) can either = 0 or 1
I'd like to write a piece of code that returns a row for each person_id in which their value for value_column is only 0 or only 1 (even though they may have 3 or 4 rows each)
It's probably an easy line of code, but for someone with less SQL experience, it seems nearly impossible!
EDIT: here is a quick sample of lines:
person_id value_column
A 0
A 1
A 0
B 0
B 0
B 0
B 0
C 1
C 1
C 1
And I would expect the line of code to return the folowing:
person_id value_column
B 0
C 1
You can try something like this probably
select distinct * from table1
where person_id in
( select person_id
from table1
group by person_id
having count(distinct value_column) <= 1
)
Inner query, will return only those person_id for which there is only one value_column present and that's the same thing getting done by count(distinct value_column) <= 1 and then outer query just selects everything for those person_id.
select * from myTable where person_id not in
(select a.person_id from myTable a, myTable b
where a.person_id = b.person_id
and a.value_column <> b.value_column)
Get persons with different values and then get those who are not in this first query.
Or quicker and nicer :
select person_id, min(value_column)
from myTable
group by person_id
having min(value_column)=max(value_column)
In mysql - table like this:
ID Name Value
1 Color Blue
1 Weight 50
1 Type Fruit
2 Color Red
2 Weight 40
3 Color Yellow
I want to get a count of distinct ID's that have a name/characteristic of 'Type' and a distinct count of ID's that don't. The first one (those that do) is easy since it's defined, but if I do a select count(distinct ID) where name <> 'type' - ID 1 will still be part of that count as it has other rows/attributes that <> 'type'.
In this example - the desired result for distinct count = 'type' would be 1 (ID 1) and for distinct count <> 'type' would be 2 (ID's 2 & 3).
Thanks in advance.
This is similar to SQL Query User has one record in the table but not another one
You can select where the id is not in a subquery looking for ids that have type
select count(id) from table where id not in (select id from table where name = 'type')
group by id
for this particular task you can use:
select count(distinct ID) from table
where ID in (select ID from table where name='type') --- this will give you count of IDs where type exists
select count(distinct ID) from table
where ID not in (select ID from table where name='type') -- this will give you count of IDs without type
SELECT id FROM test GROUP BY id HAVING
CONCAT(",",CONCAT(GROUP_CONCAT(name), ","))
NOT LIKE '%,Type,%'
will give you all ids without Type: http://sqlfiddle.com/#!2/30837/1
(Concat with , ensures, that you are not matching XType by accident.)
while
SELECT COUNT(id) AS count, GROUP_CONCAT(id) AS ids
FROM(SELECT id, count(name) as count FROM test
GROUP BY id HAVING CONCAT(",",CONCAT(GROUP_CONCAT(name), ","))
NOT LIKE '%,Type,%') as temp;
will give you the desired count: http://sqlfiddle.com/#!2/30837/9
SELECT CASE
WHEN Name='Type' THEN 'Type'
ELSE 'Non-Type'
END Name
,ID
,COUNT(ID)
FROM Stuff
GROUP BY
CASE
WHEN Name='Type' THEN 'Type'
ELSE 'Non-Type'
END
,ID
See SQLFiddle
My table content:
id aid
----------
1 1
2 2
3 2
4 4
5 4
my sql: select count(*) from table where aid in (1,2,3,4) group by aid
result:
count(*)
----------
1
2
2
I would like result:
count(*)
----------
1
2
0
2
I want a count result when aid is 1,2,3,4. What a sql should I use? Thanks for help.
(I‘m use MySQL)
-- your data
DECLARE #Data TABLE (Id int, Aid int)
INSERT INTO #Data VALUES
(1,1),
(2,2),
(3,2),
(4,4),
(5,4);
DECLARE #Relevant TABLE (Id int )
INSERT INTO #Relevant VALUES (1),(2),(3),(4);
-- the query
SELECT Relevant.Id, COUNT(Data.Aid)
FROM #Data Data
RIGHT JOIN #Relevant Relevant ON Data.Aid = Relevant.Id
GROUP BY Data.Aid, Relevant.Id
Time for an obvious statement:
- Data can't "magically appear", it needs to exist somewhere for it to appear in the output.
This is relevant for your desire to have a count of 0 for aid = 3. Because there isn't a record with aid = 3, it can't be counted. It's data that doesn't exist so will never appear in the output. So we need to force it to exist.
If you have a table that lists all of the aid entities, that's easy to do with a LEFT JOIN...
SELECT
aid.id,
COUNT(yourDataTable.aid) AS data_count
FROM
aid
LEFT JOIN
yourDataTable
ON aid.id = yourDataTable.aid
WHERE
aid.id IN (1,2,3,4)
GROUP BY
aid.id
(COUNT(yourDataTable.aid) does not count records where the field is NULL. So the 3 now exists, and the COUNT() can return 0.)
Hope this helps
SELECT COLUMN_VALUE, COUNT(BT.AID)
FROM SO_BUFFER_TABLE_15 BT, TABLE(SYS.DBMS_DEBUG_VC2COLl(1, 2, 3, 4))
WHERE BT.AID(+) = COLUMN_VALUE
GROUP BY COLUMN_VALUE
ORDER BY COLUMN_VALUE