Counting data with SQL - sql

I have a table like the first table below (sorry if it doesn't show up correctly, I'm new to StackOverflow and haven't quite gotten the hang of how to show tables in the question). I've already received help do a count of IDs that are not duplicated (I don't mean a distinct count. A distinct count would return a result of 7 (a, b, c, d, e, f, g). I wanted it to return a count of 4 (a, c, d, f). These are the IDs that do not have multiple type codes). Now I need to take it a step further to show the count of how many times within a type code has a there is an ID with only that single type code. For example, we want to see a result like the second table below. There are 2 instances of IDs that have a single type code of 444 (c, f), there is one instance of an ID that has a single type code of 111 (a), and 222 (d).
For reference, the query that got me the count of IDs that have only one type code is
select count(*) from
(select id from
mytable
group by id
having count(*) =1) t
ID|type code
a|111
b|222
b|333
c|444
d|222
e|111
e|333
e|555
f|444
g|333
g|444
Type Code|Count
111|1
222|1
444|2

maybe this is what you're asking for?
SELECT [type code],
COUNT(*) [count]
FROM mytable
WHERE [ID] IN ( SELECT [ID]
FROM mytable
GROUP BY [ID]
HAVING COUNT([type code]) = 1)
GROUP BY [type code]

You can solve this using a nested aggregation:
SELECT type_code, COUNT(*)
FROM
( -- as this looks for a single row you can simply add the type code
SELECT ID, MIN(type_code) as type_code
FROM mytable
GROUP BY ID
HAVING COUNT(*) = 1
) AS dt
GROUP BY type_code

Related

Count Distinct values in one column based on other column

I am trying to count distinct values on Z_l based on value by using with clause. Sample data exercise included below.
please look at the picture, the distinct values of Z_l based on X='ny'
with distincz_l as (select ny.X, ny.z_l o.cnt From HOPL ny join (select X, count(*) as cnt from HOPL group by X) o on (ny.X = o.Z_l)) select * from HOPL;
You don't even need a WITH clause, since you just need one single sentence:
SELECT z_l, count(1)
FROM hopl
WHERE x='ny'
GROUP BY z_l
;

How to count the number of distinct values for each specific

I have a database containing two separate fields A and B. I want to find out if for any given value of A there are multiple rows with different values of B.
I have tried using group by and distinct but I am doing something wrong, because I keep getting results which, when I query the specific value of A, all the values of B are the same. I have tried variants on the following including:
SELECT COUNT(B) FROM ex1 GROUP BY A HAVING COUNT(*) > 1;
SELECT COUNT(DISTINCT B) FROM ex1 GROUP BY A HAVING COUNT(DISTINCT B) > 1;
Strangely, this last one wound up giving me results where for a given value of B there were multiple values of A, which is backwards from what I wanted. I tried reversing A and B in the last query but that wound up giving me cases where A only had a single value of B.
How can I get records for only where there is a specific value of A in multiple records, each of which has a different value for B?
Give this a try:
"records for only where there is a specific value of A in multiple records, each of which has a different value for B?"
SELECT DISTINCT ex1a.A
FROM ex1 ex1a
WHERE
(SELECT COUNT(ex1b.B) FROM ex1 ex1b WHERE ex1a.A=ex1b.A)
= (SELECT COUNT(DISTINCT ex1b.B) FROM ex1 ex1b WHERE ex1a.A=ex1b.A)
AND
(SELECT COUNT(ex1c.B) FROM ex1 ex1c WHERE ex1a.A = ex1c.A) > 1
And, you can remove the last SELECT if you want to include the case where there is just 1 (distinct) record for A and B.
this should work:
create table want as
select a,b,count(*)as cnt from(
select a,b,count(*) as num from have
group by a, b)
group by a having cnt > 1;

How can I find out the relationship between two columns in database?

I have a view defined in SQL Server database and it has two columns A and B, both of which have the type of INT. I want to find out the relationship between these two, 1 to 1 or 1 to many or many to many. Is there a SQL statement I can use to find out?
For the relationship, it means for a given value of A, how many values of B maps to this value. If there is only one value, then it is 1 to 1 mapping.
You could use CTEs to generate COUNTs of how many distinct A values were associated with each B value and vice versa, then take the MAX of those values to determine if the relationship is 1 or many on each side. For example:
WITH CTEA AS (
SELECT COUNT(DISTINCT B) ac
FROM t
GROUP BY A
),
CTEB AS (
SELECT COUNT(DISTINCT A) bc
FROM t
GROUP BY B
)
SELECT CONCAT(
CASE WHEN MAX(bc) = 1 THEN '1' ELSE 'many' END,
' to ',
CASE WHEN MAX(ac) = 1 THEN '1' ELSE 'many' END
) AS [A to B]
FROM CTEA
CROSS JOIN CTEB
Note that any time a relationship is listed as 1, it may actually be many but just not showing that because of limited data in the table.
Demo on dbfiddle
Assuming you have no NULL values:
select (case when count(*) = count(distinct a) and
count(*) = count(distinct b)
then '1-1'
when count(*) = count(distinct a) or
count(*) = count(distinct b)
then '1-many'
else 'many-many'
end)
from t;
Note: This does not distinguish between 1-many for a-->b or b-->a.
You would use count and group by to get this information.
--This would give you count of values of b which map to every values of a. If there is at least one row with a count give you a value greater than 1 it means the mapping between a and b is one to many.
select a,count( distinct b)
from table
group by a
If all of the rows have the values equal to one for all of the elements in a then the mapping is one-one
A caveat , null in b would be ignored in count expressions. ie because null and another null is not equivalent

Sum the Count Visits - Sql

I came across a scenario and I am confused on how I can get it to work.
How can I SUM two different groups from the COUNT result?
Select Count(VisitID), Types
From Customers
Group by Types;
Result gets to be like:
Type VisitID
A 10
B 20
C 1
I want the result to be as follows:
Type VisitID
A+C 11
Thanks.
With a CTE for example:
WITH CustomerCounts ([Count], [Types])
AS
(
Select Count(VisitID), [Types]
from Customers
Group by [Types]
)
Select SUM([Count])
From CustomerCounts
Where [Types] in ('A', 'C')
Try this
Select only type you want then use pivot to convert row to column then sum column like this SELECT pv.[a] + pv.[c] from (..........)

Find Rows where the Same Two Column Values Recur

Given a table in SQL-Server like:
Id INTEGER
A VARCHAR(50)
B VARCHAR(50)
-- Some other columns
with no index on A or B, I wish to find rows where a unique combination of A and B occurs more than once.
I'm using the query
SELECT A+B, Count(A+B) FROM MyTable
GROUP BY A+B
HAVING COUNT(A+B) > 1
First Question
Is there a more time-efficient way to do this? (I cannot add indices to the database)
Second Question
When I attempt to gain some formatting of the output by including a , in the concatenation:
SELECT A+','+B, Count(A+','+B) FROM MyTable
GROUP BY A+','+B
HAVING COUNT(A+','+B) > 1
The query fails with the error
Column 'MyDB.dbo.MyTable.A' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
with a similar error for Column B.
How can I format the output to separate the two columns?
It would seem more natural to me to write:
SELECT A, B, Count(*) FROM MyTable
GROUP BY A, B
HAVING COUNT(*) > 1
And it's the most efficient way of doing it (and so is the query in the question).
Similarly to the above query, you can rewrite your second query:
SELECT A + ',' + B, Count(*) FROM MyTable
GROUP BY A, B
HAVING COUNT(*) > 1