Selecting distinct values - sql

Trying to get a selection of records where if COUNT ([WHO]) > 1 then select [WHO] where the [LIT] <> 0.
Example if [WHO] = '12082132' , '12082132' and [LIT] = 0, then ignore [WHO].
WHO LIT COUNT
3517015 7 1
3523687 0 1
12057744 0 2
12058316 7 1
12059820 7 1
12082132 2 2
12082132 5 1
12082132 1 3
12082132 14 1
12082132 0 1
I have tried grouping, case statements, but I think I am trying to get something that is not possible. Any help will do.
Expected results
WHO LIT COUNT
3517015 7 1
12058316 7 1
12059820 7 1

Trying to get a selection of records where if COUNT ([WHO]) > 1 then select [WHO] where the [LIT] <> 0.
Is this what you want?
select t.*
from (select t.*, count(*) over (partition by who) as cnt
from t
) t
where cnt > 1 and lit <> 0;

You can use not exists & use window function :
select t.*, count(*) over (partition by t.who) as cnt
from table t
where not exists (select 1
from table t1
where t1.who = t.who and t1.lit = 0
);

Simple NOT IN will work
SELECT * FROM #Table
WHERE [WHO] NOT IN (
SELECT DISTINCT [WHO]
FROM #Table
WHERE CASE WHEN [LIT] >= 1 THEN 0 ELSE 1 END = 1
)

This is an example, I hope it helps you,I think that it does what you want but its a little tricky, maybe can lead you to an answers at least if it's not
what you want.
drop table #testMr
drop table #checkTest
create table #testMr(who numeric, lit numeric, count_x numeric)
create table #checkTest(who numeric, lit numeric, count_x numeric,countWho numeric)
insert into #testMr values(3517015,7,1)
insert into #testMr values(3523687,0,1)
insert into #testMr values(12057744,0,1)
insert into #testMr values(12058316,7,1)
insert into #testMr values(12082132,1,3)
insert into #testMr values(12082132,14,1)
insert into #testMr values(12082132,7,1)
insert into #testMr values(12082132,0,1)
insert into #checkTest
select who,sum(lit) as [lit],sum(count_x) as [CountX],count(who) as [CountWho] from #testMr
where who in(select b.who from #testMr as b where b.lit<>0) group by who having count(who)>1
if(select count(*) from #checkTest)>0
begin
--there are some invalid values so we filter by the lit<>0 and remove the invalid ones.
select * from #testMr where lit<>0 and who not in(select b.who from #checkTest as b)
end
else
begin
--'All values are Ok and we filter by the count who.'
select who,sum(lit) as [lit],sum(count_x) as [CountX] from #testMr group by who having count(who)>1
end

Related

Conditional SQL logic

I have a simple table of voting frequencies of registered voters
create table public.campaign_202206 (
registrant_id INTEGER not null references votecal.voter_registration (registrant_id),
voting_frequency smallint
);
I want to insert values into this table with the count of elections that the voter has participated in among the past four elections:
insert into campaign_202206 (
select registrant_id, count(*)
from votecal.voter_participation_history
where election_date in ('2021-09-14', '2020-11-03', '2020-03-03', '2018-11-06')
group by registrant_id
);
However, if the count is 1, then I want to look at the participation from five elections ago on '2018-06-05' and if there is no participation in that election, I want to store the voting_frequency as 0 instead of 1.
insert into campaign_202206 (
select
registrant_id,
case
when count(*) = 1 then --- what goes here?
else count(*)
end as voting_frequency
from votecal.voter_participation_history
where election_date in ('2021-09-14', '2020-11-03', '2020-03-03', '2018-11-06')
group by registrant_id
);
What would go in this case-when-then to get the value for this special case?
Use a correlated subquery as foloows:
insert into campaign_202206 (
select
registrant_id,
case when count(*) = 1 then
(
select count(*)
from votecal.voter_participation_history sqvph
where sqvph.election_date = '2018-06-05'
and sqvph.registrant_id = vph.registrant_id
)
else count(*)
end as voting_frequency
from votecal.voter_participation_history vph
where election_date in ('2021-09-14', '2020-11-03', '2020-03-03', '2018-11-06')
group by registrant_id
);
The resultset providers in the query need aliases for this to work.
User nested case:
insert into campaign_202206 (
select
registrant_id,
case
when count(*) = 1 then
case
when (select count(*) from voter_participation_history
where election_date in ('2018-06-05') and registrant_id
= v1.registrant_id) > 0
then 1
else 0
end
else count(*)
end as voting_frequency from voter_participation_history v1 where
election_date in ('2021-09-14', '2020-11-03', '2020-03-03', '2018-11-06')
group by v1.registrant_id);

Count value across multiple columns

I am looking to count the number of times set of values occurred in a table. These values could occur in up to 10 different columns. I need to increment the count regardless of which column it is in. I know how I could count if they were all in the same column but not spanning multiple columns.
Values can be added in any order. I have about a thousand
Cpt1 Cpt2 Cpt3 Cpt4 Cpt5
63047 63048 63048 NULL NULL
I would want to for this row I'd expect this as the result
63047 1
63048 2
You could use a union all call to treat them as one column:
SELECT col, COUNT(*)
FROM (SELECT col1 FROM mytable
UNION ALL
SELECT col2 FROM mytable
UNION ALL
SELECT col3 FROM mytable
-- etc...
) t
GROUP BY col
It's not entirely clear what your table exactly looks like, but I'm guessing that what you're looking for is:
SELECT row_count = COUNT(*),
row_count_with_given_value = SUM ( CASE WHEN field1 = 'myValue' THEN 1
WHEN field2 = 'myValue' THEN 1
WHEN field3 = 'myValue' THEN 1
WHEN field4 = 'myValue' THEN 1 ELSE 0 END)
FROM myTable
Assuming the fieldx columns are not NULL-able, you could write it like this too:
SELECT row_count = COUNT(*),
row_count_with_given_value = SUM ( CASE WHEN 'myValue' IN (field1, field2, field3, field4) THEN 1 ELSE 0 END)
FROM myTable
Something like this might work (after adapting to your value domain and data types):
create table t1
(i1 int,
i2 int,
i3 int);
insert into t1 values (1,0,0);
insert into t1 values (1,1,1);
insert into t1 values (1,0,0);
declare #i int = 0;
select #i = #i + i1 + i2 + i3 from t1;
print #i;
drop table t1;
Output is: 5
Many databases support lateral joins, of one type of another. These can be used to simplify this operation. Using the SQL Server/Oracle 12C syntax:
select v.cpt, count(*)
from t cross apply
(values (cpt1), (cpt2), . . .
) v(cpt)
where cpt is not null
group by v.cpt;

How to check If table contains diferent values?

I have table:
Id Value
1 79868
2 79868
3 79868
4 97889
5 97889
Now, I want to make next select with bool variable that check if table contains difrent values at table column Value. Something like this:
select
v= (select case when exists(...)
then 1
else 0
end)
Table contais Values: 79868, 97889 so v should return 1 in other case 0.
How to write select iniside select case??
You can compare the min and max values:
select (case when (select min(value) from t) = (select max(value) from t)
then 1 else 0
end) as all_same
With an index on (value), this should be quite fast.
The above solution assumes that there are no null values or that NULL values should be ignored.
You might try this:
SELECT CASE COUNT(*)
WHEN 1 THEN 1
ELSE 0
END AS all_equal
FROM (SELECT DISTINCT Value FROM my_table);
If I get your question correct, you want to check if value column contains more than 1 distinct values. You can achieve this using,
select (case when count(value) > 1 then 1 else 0 end) as out
from (select value from table group by value) temp
May this is better:
SELECT CASE COUNT(DISTINCT value) WHEN 1 THEN 1
ELSE 0
END AS all_equal
FROM my_table;
So, you just need one case expression with two Boolean variable
declare #bit1 bit = 1, #bit0 bit = 0
select
(case when min(value) = max(value) then #bit1 else #bit0 end) as v
from table t
where value is not null
This is a the same as another answers
But is has some test data
declare #T table(pk int identity primary key, val int not null);
insert into #T (val) values (79868), (79868), (79868);
select case when count(distinct(val)) = 1 then 0 else 1 end as dd
from #t t;
select case when min(val) = max(val) then 0 else 1 end as dd
from #t t;
insert into #T (val) values (97889), (97889);
select case when count(distinct(val)) = 1 then 0 else 1 end as dd
from #t t;
select case when min(val) = max(val) then 0 else 1 end as dd
from #t t;
I like the min max answer from Gordon best

How best to Count(*) with a CASE STATEMENT?

The following SQL (on SQL Server) returns an error of:
Incorrect syntax near '*'
Is there something inherently wrong with using the following SELECT statement?:
SELECT
COUNT(CASE WHEN <conditions> THEN * ELSE NULL END) as conditionalcountall
FROM TABLE
I tried this variation which also failed:
SELECT
CASE WHEN <conditions> THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM TABLE
I tend to like sum()
SELECT
SUM(CASE WHEN <conditions> THEN 1 ELSE 0 END) as conditionalcountall
FROM TABLE
Try This, it is Tested
SELECT
CASE WHEN 1 = 1 THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM TABLE
1 = 1is example conditions
Demo:-
Create table #temp (id int , col1 varchar (10))
go
insert into #temp values (1 , 'aaaa')
insert into #temp values (2 , 'bbbb')
insert into #temp values (3 , 'cccc')
SELECT
CASE WHEN 1 = 1 THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM #temp
Result:
In Case Condation like that id = 1 you should select Count(*) in CASE cluse in your query
like this:
SELECT
CASE WHEN id = 1 THEN (select COUNT(*) from #temp) ELSE NULL END as conditionalcountall
FROM #temp
Result:-
Note: if You used Count(*) directly, you counted the id column, so you should use group by as next:
SELECT
CASE WHEN id = 1 THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM #temp
group by id
Result:
SELECT
CASE WHEN X THEN Y
ELSE Z
END *NEW COLUMN NAME*
, COUNT(*)
FROM
TABLE
GROUP BY
*NEW COLUMN NAME*
This should return two columns, one with the buckets/case statement and one with the count of the columns for each one of your buckets
This method was the most straightforward for myself
If you REALLY, REALLY want to use COUNT, then you can do this:
SELECT
COUNT(*)
FROM table
WHERE <conditions>

SQL Specific Item on top

I am having this query for a photo contest:
SELECT * FROM `users` ORDER BY entry_id DESC
The result gives 10 records with entry_id 10, 9, 8, 7, ......1
What can I do to pick a specific entry on the top?
As there is a requirement if there is a refer ID, entry show first.
So the expected result should be: 4,10,9,8,7,6,5,3,2,1 if 4 if a refer ID.
Try this:
SELECT *
FROM `users`
ORDER BY (CASE WHEN entry_id = 4 THEN 0 ELSE 1 END), entry_id DESC;
for more Dynamic Approach create table value Function
create function OrderData(#a int)
returns #t table ( id int)
as
begin
insert into #t
SELECT *
FROM ab
ORDER BY (CASE WHEN id = #a THEN 0 ELSE 1 END), id DESC
return;
end;
select * from dbo.abc(4)
output
4,10,9,8,7,6,5,3,2,1
select * from dbo.abc(5)
output
5,10,9,8,7,6,4,3,2,1