I want a case statetement that count more than 1 as 1 - sql

Please help solve the below query.
The column in question has Y and N and I want the N to show zero and the Y to show 1.
I want it to aggregate the no of times visited for each machine and if >= 1 to show 1. Client requirement is whether machine has been visited regardless of the number of times.
Select MachineNo,
[Date_of_Visit],
Month([Date_of_Visit])[Month],
Year([Date_of_Visit])[Year],
sum(case when [Visited] = 'Y' then 1 else 0 end)[No of Visits]
FROM [MachineVisit]
Group by [Date_of_Visit],
[MachineNo]

Use Max instead of Sum
Max(case when [Visited] = 'Y' then 1 else 0 end)[Visits]

This is a little confusing, the way it is written, but I am assuming you want something like:
select sum(case when [visited] >1 then 1 else null end) visists
from visit_table
where visit_date = '2015-01-30'
This is assuming that you have a table that counts the visits for a single day for 1 IP address as single entry.
If you have a table that has an entry for every single page visit, then you would probably need to do:
select count(distinct ip_address)
from (
select ip_address
from visit_table
where visit_date = '2015-01-30'
group by ip_address
having count(1) >1
) x
EDIT:
Well then the simplist way should be:
select count(1)
from visit_table
where [visited]='Y'
and visit_date = '2015-01-30'
;
That should work...
Although I don't have the table in front of me - so if this doesn't work, please post the fully query.

Related

Is there a way to collect the data and inspect in one pass using groupby function

Sample Data of table_1
Have this Query that returns
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0 END) AS num_activity_a_or_b
from table_1
group by customer
Results:
Want to extend this to return one more column if for a given code say X1 if the Activity is "a" and "c" then return num_of_a_and_c_activity.
A bit stuck how to collect and inpect the code and activities in one pass.
can we combine windowing function to achieve this.
Please advise and help
UPDATE:
based on the updated results, maybe the below query is what you need
So what i assume is that you need both a and c as well x1 .
So I count distinct activities which are a and c and then do integer division by 2. if only a is present then count distinct =1 but 1/2 =0 in integer division.
It is only 1 when both a and c are present.
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0
END) AS num_activity_a_or_b,
COUNT(DISTINCT CASE WHEN code IN ('x1') AND activity IN ( 'a','c')
THEN activity
ELSE NULL
END)/2 AS num_activity_a_and_c
from table_1
group by customer
Maybe your query can be
select
customer,
SUM(CASE WHEN activity IN ( 'a','b')
THEN 1
ELSE 0
END) AS num_activity_a_or_b,
SUM(CASE WHEN code IN ('x1') AND activity IN ( 'a','c')
THEN 1
ELSE 0
END) AS num_activity_a_or_c
from table_1
group by customer

sql group by satisfying multiple conditions within the group

I have a table like below:
I want to select the group which has RELB_CD =9093 and INFO_SRC_CD with 7784. Both conditions should be present in the group. In the table below my output should be the group with id=139993690.
You can use aggregation with having:
select id
from t
group by id
having sum(case when relb_cd = 9093 then 1 else 0 end) > 0 and
sum(case when info_src_cde = 7784 then 1 else 0 end) > 0
hey use this code hope this will help you.
you have to ignore the date column because that one is not allowing to group
select id,fisc_ind, sum(sls_amt),relb_cd,info_scop,info_src_cd from yourtable group by id,fisc_ind,relb_cd,info_scop,info_src_cd
Another working answer. If your data are large, you could compare both GL's and this working answer and see which runs faster for you. I honestly don't know which is faster. This was slightly faster with a very short set of data.
select id
from table1
where relb_cd = 9093
intersect
select id
from table1
where info_src_cd = 7784

How do I check if a certain value exists?

I have a historization table called CUR_VALID. This table looks something like this:
ID CUR_VALID
1 N
1 N
1 Y
2 N
2 Y
3 Y
For every ID there needs to be one Y. If there is no Y or multiple Y there is something wrong. The statment for checking if there are multiple Y I already got. Now I only need to check for every ID if there is one Y existing. Im just not sure how to do that. This is what I have so far. So how do I check if the Value 'Y' exists?
SELECT Count(1) [Number of N]
,MAX(CUR_VALID = 'N')
,[BILL_ID]
,[BILL_MONTH]
,[BILL_SRC_ID]
FROM db.dbo.table
GROUP BY [BILL_ID]
,[BILL_MONTH]
,[BILL_SRC_ID]
Having MAX(CUR_VALID = 'N') > 1
Why are you fiddling with 'N' when you are interested in 'Y'?
Use conditional aggregation to get the count of the value your are interested in.
SELECT
COUNT(*) AS number_of_all,
COUNT(CASE WHEN cur_valid = 'Y' THEN 1 END) AS number_of_y,
COUNT(CASE WHEN cur_valid = 'N' THEN 1 END) AS number_of_n,
bill_id,
bill_month,
bill_src_id,
FROM db.dbo.table
GROUP BY bill_id, bill_month, bill_src_id;
Add a HAVING clause in order to get only valid
HAVING COUNT(CASE WHEN cur_valid = 'Y' THEN 1 END) = 1
or invalid
HAVING COUNT(CASE WHEN cur_valid = 'Y' THEN 1 END) <> 1
bills.
The following query will give you the list of id for which your integrity condition is not met: For every ID there needs to be one Y. If there is no Y or multiple Y there is something wrong.
select T1.id from table T1 where (select count(*) from table T2 where T2.id=T1.id and T2.CUR_VALID='Y')!=1
This query returns both not having at least one 'Y' value and more than one 'Y' value ID's.
First, sum up the Y values and relate to each id, then select not 1 ones from that table.
select * from (
select ID, SUM(case when CUR_VALID = 'Y' then 1 else 0 end) as CNT
from table
group by ID
) b where b.CNT <> 1
DBFiddle
As I understand, you want to get all the id for which your integrity check passes. And integrity check for you means, there is only one row with CUR_VALID value equal to Y in the CUR_VALID table.
This can be achieved by a group by clause:
select id from CUR_VALID
where CUR_VALID.CUR_VALID = 'Y'
group by id
having count(CUR_VALID.CUR_VALID) = 1;

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

SQL Count with multiple conditions then join

Quick one,
I have a table, with the following structure
id lid taken
1 1 0
1 1 0
1 1 1
1 1 1
1 2 1
Pretty simply so far right?
I need to query the taken/available from the lid of 1, which should return
taken available
2 2
I know I can simply do two counts and join them, but is there a more proficient way of doing this rather than two separate queries?
I was looking at the following type of format, but I can not for the life of me get it executed in SQL...
SELECT
COUNT(case taken=1) AS taken,
COUNT(case taken=0) AS available FROM table
WHERE
lid=1
Thank you SO much.
You can do this:
SELECT taken, COUNT(*) AS count
FROM table
WHERE lid = 1
GROUP BY taken
This will return two rows:
taken count
0 2
1 2
Each count corresponds to how many times that particular taken value was seen.
Your query is correct just needs juggling a bit:
SELECT
SUM(case taken WHEN 1 THEN 1 ELSE 0 END) AS taken,
SUM(case taken WHEN 1 THEN 0 ELSE 1 END) AS available FROM table
WHERE
lid=1
Alternatively you could do:
SELECT
SUM(taken) AS taken,
COUNT(id) - SUM(taken) AS available
FROM table
WHERE
lid=1
SELECT
SUM(case WHEN taken=1 THEN 1 ELSE 0 END) AS taken,
SUM(case WHEN taken=0 THEN 1 ELSE 0 END) AS available
FROM table
WHERE lid=1
Weird application of CTE's:
WITH lid AS (
SELECT DISTINCT lid FROM taken
)
, tak AS (
SELECT lid,taken , COUNT(*) AS cnt
FROM taken t0
GROUP BY lid,taken
)
SELECT l.lid
, COALESCE(a0.cnt, 0) AS available
, COALESCE(a1.cnt, 0) AS taken
FROM lid l
LEFT JOIN tak a0 ON a0.lid=l.lid AND a0.taken = 0
LEFT JOIN tak a1 ON a1.lid=l.lid AND a1.taken = 1
WHERE l.lid=1
;