How do I count distinct to exclude a value? - sql

Below is the different scales in a POS system. I am trying to count the number of distinct scales that are not 'MANUAL WT'.
This is what I have, but it is returning 2 and not 6.
count (distinct (case when d.SCALE_IN_ID != 'MANUAL WT' then 1 else 0 end)) as Num_Scale

Consider:
select count(distinct case when scale_in_id <> 'MANUAL WT' then scale_in_id end) cnt
from mytable
The problem with your original query is that the case expression turns values to either 0 and 1, and then the aggregate function computes how many distinct values are returned: since values are all 0s or 1s, there are only two distinct values (or one in edge cases): hence the result that you are getting.

A simple WHERE clause will do:
select count(distinct scale_in_id) Num_Scale
from tablename
where scale_in_id <> 'MANUAL WT'

Related

SQL: identify if there are multiples (not duplicates) in a column

I am currently struggling in identifying a possibility to identify certain patterns in my data using SSMS.
I wish to identify rows that contain multiples (x2, x3, or x*4) of an entry within the same column.
I really have no clue on how to even start my "where" statement right now.
SELECT [numbers], [product_ID]
FROM [db].[dbo].[tablename]
WHERE [numbers] = numbers*2
My problem is that with the code above I can obviously only identify zeros.
Google only helps me out with finding duplicates but I can't find a way to identify multiples of a value...
My desired result would be a table that only contains numbers (linked to product_IDs) that are multiples of each other
Anyone can help me out here?
If a column contains multiples, then all are multiples of the smallest non-zero value. Let me assume the values are positive or zero for this purpose.
So, you can determine if this is the case using window functions and modulo arithmetic:
select t.*
from (select t.*,
min(case when number > 0 then number end) over () as min_number
from t
) t
where number % min_number = 0 or min_number = 1;
If you want to know if all numbers meet this criteria, use aggregation:
select (case when min(number % min_number) = 0 then 'all multiples' else 'oops' end)
from (select t.*,
min(case when number > 0 then number end) over () as min_number
from t
) t
My desired result would be a table that only contains numbers (linked to product_IDs) that are multiples of each other
You'll need to test all pairs of rows, which means a CROSS JOIN.
Something like this:
with q as
(
SELECT [numbers],
[product_ID],
cast(a.numbers as float) / coalesce(b.numbers, null) ratio
FROM [tablename] a
CROSS JOIN [tablename] b
)
select *
from q
where ratio = cast(ratio as bigint)
and ratio > 1

SQL Count Distinct returning one extra count

How is this possible that these two methods are returning different results?
Method 1 (returns correct count):
SELECT COUNT(DISTINCT contact_id)
FROM Traffic_Action
WHERE action_type IN ('Schedule a Tour', 'Schedule Follow-up', 'Lost')
Method 2 (returns one extra count):
SELECT COUNT(DISTINCT CASE WHEN action_type IN ('Schedule a Tour', 'Schedule Follow-up', 'Lost') THEN contact_id ELSE 0 END)
FROM Traffic_Action
Remove the else part - as 0 is also counted
SELECT COUNT(DISTINCT CASE WHEN
action_type in ('Schedule a Tour','Schedule Follow-up','Lost') THEN contact_id END)
FROM Traffic_Action
No wonder you are getting two different results.
First query:
Provides you the distinct count of records where action_type in Schedule a Tour, Schedule Follow-up and Lost
SELECT COUNT(DISTINCT contact_id) FROM Traffic_Action WHERE action_type in
('Schedule a Tour','Schedule Follow-up','Lost')
Second query:
In this query any value apart from Schedule a Tour, Schedule Follow-up and Lost is considered as 0, and on taking distinct value, results one row according to your case statement
SELECT COUNT(DISTINCT CASE WHEN action_type in ('Schedule a Tour','Schedule Follow-
up','Lost') THEN contact_id ELSE 0 END) FROM Traffic_Action
In simple words,
In first query you are filtering only three values
In second query you have no filters, but case statement on three values and else condition to return 0 for non matching criteria
That means you have 1 record where contact_id is NULL. Normally, COUNT() ignores NULL values. Your second query converts NULL to zero via the "ELSE" branch. That should be why you see a difference.
You can quickly see for yourself in this example. This will return 2 although there are 3 records
select count(distinct a.col1)
from (
select 1 as Col1
union select 2
union select NULL
) a

Count different values of 0 from a MySQL query

I'm trying to make this query:
SELECT monthPosted,
sector,
COUNT(sumaAbas) as abasNum,
SUM(sumaAbas) as abas,
COUNT(usdAmount) AS totalNum,
SUM(usdAmount) AS total
FROM DatosSpend
WHERE negotiableProcGl='Y'
GROUP BY sector
The problem I'm getting here is that the COUNT(usdAmount) is counting all values also having a 0 in it.
How can I ignore the count of values=0?
Aggregate functions ignore nulls. You could use a case expression to convert 0s to nulls and thus skip them. E.g.:
SELECT monthPosted,
sector,
COUNT(sumaAbas) as abasNum,
SUM(sumaAbas) as abas,
COUNT(CASE usdAmount WHEN 0 THEN NULL ELSE 1 END) AS totalNum,
SUM(usdAmount) AS total
FROM DatosSpend
WHERE negotiableProcGl = 'Y'
GROUP BY sector
You can just simply exclude the 0 values in the WHERE clause:
WHERE negotiableProcGl='Y' AND value != 0
Where value is your column name

Sum distinct records in a table with duplicates in Teradata

I have a table that has some duplicates. I can count the distinct records to get the Total Volume. When I try to Sum when the CompTia Code is B92 and run distinct is still counts the dupes.
Here is the query:
select
a.repair_week_period,
count(distinct a.notif_id) as Total_Volume,
sum(distinct case when a.header_comptia_cd = 'B92' then 1 else 0 end) as B92_Sum
FROM artemis_biz_app.aca_service_event a
where a.Sales_Org_Cd = '8210'
and a.notif_creation_dt >= current_date - 180
group by 1
order by 1
;
Is There a way to only SUM the distinct records for B92?
I also tried inner joining the table on itself by selecting the distinct notification id and joining on that notification id, but still getting wrong sum counts.
Thanks!
Your B92_Sum currently returns either NULL, 1 or 2, this is definitely no sum.
To sum distinct values you need something like
sum(distinct case when a.header_comptia_cd = 'B92' then column_to_sum else 0 end)
If this column_to_sum is actually the notif_id you get a conditional count but not a sum.
Otherwise the distinct might remove too many vales and then you probably need a Derived Table where you remove duplicates before aggregation:
select
repair_week_period,
--no more distinct needed
count(a.notif_id) as Total_Volume,
sum(case when a.header_comptia_cd = 'B92' then column_to_sum else 0 end) as B92_Sum
FROM
(
select repair_week_period,
notif_id
header_comptia_cd,
column_to_sum
from artemis_biz_app.aca_service_event
where a.Sales_Org_Cd = '8210'
and a.notif_creation_dt >= current_date - 180
-- only onw row per notif_id
qualify row_number() over (partition by notif_id order by ???) = 1
) a
group by 1
order by 1
;
#dnoeth It seems the solution to my problem was not to SUM the data, but to count distinct it.
This is how I resolved my problem:
count(distinct case when a.header_comptia_cd = 'B92' then a.notif_id else NULL end) as B92_Sum

How to count the rows which contains non zero values in sql

SELECT round(COUNT(dmd_1wk),2) AS NBR_ITEMS_1WK
FROM table;
Field dmd_1wk has so many zeros in it. How do I Count the non zero values?
It sounds like you just need to add a WHERE clause:
SELECT
round(COUNT(dmd_1wk),2) AS NBR_ITEMS_1WK
FROM table
WHERE dmd_1wk <> 0;
If you want the count of both non-zero and zero values, then you can use something like:
SELECT
round(COUNT(case when dmd_1wk <> 0 then dmd_1wk end),2) AS NBR_ITEMS_1WK_NonZero,
round(COUNT(case when dmd_1wk = 0 then dmd_1wk end),2) AS NBR_ITEMS_1WK_Zero
FROM table;
Method 1: Case Statement. This may be useful if you need to continue to process all rows (which a where clause would prevent).
SELECT count(case when dmd_1wk = 0 then 0 else 1 end) as NonZeroCount FROM MyTable
Method 2: Where Clause.
SELECT
count(1) as NonZeroCount
FROM
MyTable
WHERE
dmd_1wk <> 0
I'd like to offer another solution using NULLIF since COUNT won't count NULL values:
SELECT round(COUNT(NULLIF(dmd_1wk,0)),2) AS NBR_ITEMS_1WK
FROM table;
And here is the Fiddle.
Good luck.
Methinks bluefeets answer is probably what you are really looking for, as it sounds like you just want to count non-zeros; but this will get you a count of zero and non-zero items if that's not the case:
SELECT
ROUND(SUM(CASE NVL(dmd_1wk, 0) = 0 THEN 1 ELSE 0 END), 2) AS "Zeros",
ROUND(SUM(CASE NVL(dmd_1wk, 0) != 0 THEN 1 ELSE 0 END), 2) AS "NonZeros"
FROM table
Although there is no point in rounding a whole number, I've included your original ROUNDs as I'm guessing you're using it for formatting, but you might want to use:
TO_CHAR(SUM(...), '999.00')
as that's the intended function for formatting numbers.
You can filter them.
SELECT round(COUNT(dmd_1wk),2) AS NBR_ITEMS_1WK
FROM table
WHERE dmd_1wk <> 0;