1 result using COUNT in multiple columns Using sql - sql

I have table called questions Survey. I sent them a survey in Jan_2018, March_2018, Sept_2018, Jan_2017, March_2017, Sept_2017. I'm trying to get the sum of people that received the email and answer the questions. The table only has YES( Y), NO (N)]. Not sure, if this queries is the best to use as it gave me a lower numbers that I think is incorrect. I used this queries:
SELECT COUNT (*) AS 'Questions_Results'
FROM [DEV].[dbo].[Questions_survey]
WHERE [Jan_2018] = 'Y'
AND [March_2018] = 'Y'
AND [Sept_2018] = 'Y'
AND [Jan_2017] = 'Y'
AND [March_2017] = 'Y'
AND [Sept_2017] = 'Y'
AND [2017_Jan_Test_open] = 'Y'
AND [2017_March_Test_open] = 'Y'
AND [2017_Sept_Test_open] = 'Y'

If you want the overall number of people who answered your survey, just use OR instead of AND :
SELECT COUNT (*) AS 'Questions_Results'
FROM [DEV].[dbo].[Questions_survey]
WHERE [Jan_2018] = 'Y'
OR [March_2018] = 'Y'
OR [Sept_2018] = 'Y'
OR [Jan_2017] = 'Y'
OR [March_2017] = 'Y'
OR [Sept_2017] = 'Y'
OR [2017_Jan_Test_open] = 'Y'
OR [2017_March_Test_open] = 'Y'
OR [2017_Sept_Test_open] = 'Y'
I think this is the best way to do it.

AND returns the count of records where survey has been generated for all months. If you want total individual survey numbers use OR
SELECT COUNT (*) AS 'Questions_Results' FROM [DEV].[dbo].[Questions_survey] WHERE [Jan_2018] = 'Y' OR [March_2018] = 'Y' OR [Sept_2018] = 'Y' OR [Jan_2017] = 'Y' OR [March_2017] = 'Y' OR [Sept_2017] = 'Y' OR [2017_Jan_Test_open] = 'Y' OR [2017_March_Test_open] = 'Y' OR [2017_Sept_Test_open] = 'Y'

If you want the number of emails sent, then presumably you want:
SELECT COUNT(*) AS Questions_Results
FROM [DEV].[dbo].[Questions_survey]
WHERE 'Y' IN (Jan_2018, March_2018, Sept_2018, Jan_2017, March_2017, Sept_2017);
I'm not sure what the "test_open" columns are. They are not mentioned in the question itself. Are they related to "answering the questions"?
If a "person" can be on more than one row, then you may need COUNT(DISTINCT) using whatever column specifies the person:
SELECT COUNT(DISTINCT person_id) AS Questions_Results
FROM [DEV].[dbo].[Questions_survey]
WHERE 'Y' IN (Jan_2018, March_2018, Sept_2018, Jan_2017, March_2017, Sept_2017);

Related

Why Would Unknown Column Be Referenced in SQL Query

I am in the process of updating some SQL queries to run against MariaDB instead of via SQL Anywhere. One query I'm running is erroring with this:
Error Code: 1054. Unknown column 'choice' in 'field list'
That is for this query:
SELECT
(select firstname||' '||lastname||' ('||service||')' from staff_members where id_number = customer_assignment_reviews.staff_member_id) as Rep,
(select customer_firstname||' '|| customer_lastname from customers where id_number = customer_assignment_reviews.cs_id) as Cus,
last_modified as "Response Date",replace(review_reason,'’','') as "Reason",
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
FROM customer_assignment_reviews
where staff_member_id in (Select id_number from kar.staff_members where division_id = 6)
and "Response Date" between today() - 7 and today() /* Date Range */
and "Accepted?" = 'No'
Order by 3 desc
Is this error message as straightforward as it sounds? It's simply saying the column "choice" doesn't exist on the target table?
I'm just trying to reason through why this code (which I inherited) would be referencing a column that does not exist. Could something be expected here at runtime?
You don't need to use subquery in SELECT list
SELECT
-- ...
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
=>
SELECT
CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end as "Accepted?"
Additionaly syntax SELECT alias = expression is only T-SQL specific:
SELECT alias = 1
<=>
SELECT 1 AS alias
What is this supposed to mean?
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
Very importantly, a select is not needed here. You might mean:
(case when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as is_accepted -- prefer to not have to need escape characters
If accepted only takes those two values, you can simplify this to:
elt(accepted + 1, 'No', 'Yes') as is_accepted

Venn operation in SQL query

I have a table with list of employees who can be admin, dev, both or none
EMP_ID IS_ADMIN IS_DEV
1 Y Y
2 Y N
3 N Y
4 N N
I want to write a query so that when I request
IS_ADMIN=Y returns 1,2
IS_DEV=Y returns 1,3
IS_DEV=Y, IS_ADMIN=Y returns 1,2,3
IS_DEV=N, IS_ADMIN=N or nothing returns 4
Is there anyway to incorporate this login in one query?
You specify all the options as parameters, passing null to any parameter you don't care for and checking for null as a query condition. Your logic is a bit bent so it have to be programmed for exactly, every combination:
SELECT
emp_id
FROM
emps
WHERE
(is_admin = 'Y' AND :isadmin = 'Y' AND :isdev is null)
OR
(is_dev = 'Y' AND :isdev = 'Y' AND :isadmin is null)
OR
(:isadmin = 'Y' AND :isdev = 'Y' AND (is_admin = 'Y' OR is_dev = 'Y'))
OR
(COALESCE(:isadmin, 'N') = 'N' AND COALESCE(:isdev, 'N') = 'N' AND is_admin = 'N' AND is_dev = 'N')
Your calling language of choice would set the parameters to 'Y', 'N' or null if it had no opinion, e.g. in c# for your case 1:
sqlCommand.Parameters["isadmin"].Value = "Y";
sqlCommand.Parameters["isdev"].Value = DBNull.Value;
using(var reader = sqlCommand.ExecuteReader()) ....

How to add where condition if result count is greater than one

I want to build SQL query that returns unique id.
My problem is that i need to add another condition to query if i have more than one result.
select u.id
from users u
where u.id in ('1','2','3')
and u.active = 'Y'
if i get more than one result i need to add:
and u.active_contact = 'Y'
I tried to build this query
select * from (
select u.id, count(u.id) as results
from users u
where u.id in ('1','2','3')
and u.active = 'Y'
group by u.id
) tab
If(tab.results > 1) then
where tab.u.active_contact = 'Y'
end
Thanks in advanced.
Hope i explained my self good enough.
Here's a different approach:
SELECT id
FROM (SELECT id, (CASE WHEN active ='Y' THEN 1 ELSE 0 END) + (CASE WHEN active_contact ='Y' THEN 1 ELSE 0 END) as actv FROM users ORDER BY actv DESC)
WHERE actv > 0
LIMIT 1
The subquery adds a column which aggregates active and active_contact. The main SELECT then optimizes the combination of these two fields, requiring at least one of them. I believe this provides the intended result.
Among the possible ways to solve this, here are two.
1) Use the active_contact id. If there is none use another id.
select coalesce( max(case when active_contact = 'Y' then id end), max(id) ) as id
from users
where id in ('1','2','3')
and active = 'Y';
2) Sort with active_contact coming first. Then get the first record.
select id
from
(
select id
from users
where id in ('1','2','3')
and active = 'Y'
order by case when active_contact = 'Y' then 1 else 2 end
) where rownum = 1;
A method using Analytic functions
SELECT id
FROM (SELECT u.id
, u.active_contact
, count(*) OVER () actives
FROM users u
WHERE u.id IN ('1','2','3')
AND u.active = 'Y')
WHERE ( actives = 1
OR ( actives > 1
AND active_contact = 'Y'))
If there is more than one record where active = 'Y' AND active_contact = 'Y' it will return them all. If only one of these is required you will need to identify the criteria for choosing that one.

How can I write this select query in SQL Server?

I need to extract some data to analyse exceptions/logs, and I'm stuck at a point.
I have a table with a column called CallType, and a status which can be Success or Failure. This table also has a column called SessionId.
I need to do this:
Select all the SessionId's where all the CallType = 'A' are marked as Success, but there is at least one CallType = 'B' having a Failure for that session.
There will be a where clause to filter out some stuff.
I'm thinking something like:
select top 10 *
from Log nolock
where ProviderId=48 -- add more conditions here
group by SessionId
having --? what should go over here?
I would do this with conditional aggregation in the having clause:
select top 10 *
from Log nolock
where ProviderId=48 -- add more conditions here
group by SessionId
having sum(case when CallType = 'A' and Status = 'Failure' then 1 else 0 end) = 0 and
sum(case when CallType = 'B' and Status = 'Failure' then 1 else 0 end) > 0 and
sum(case when CallType = 'A' and Status = 'Success' then 1 else 0 end) > 0;
The having clause checks for three conditions by counting the number of rows that meet each one. If = 0, then no records are allowed. If > 0 then records are required.
That CallType A has no failures.
That CallType B has at least one failure.
That at least one CallType A success exists.
The third condition is ambiguous -- if is not clear if you actually need CallType As to be in the data, based on the question.
SELECT *
FROM Log L WITH(NOLOCK)
WHERE L.CallType='A'
AND L.[Status] = 'Success'
AND L.ProviderId = 48
AND EXISTS (SELECT 1
FROM Log
WHERE L.SessionID = SessionID
AND CallType='B'
AND [Status] = 'Failure')
Having clause can only operate on aggregates within the group so this isn't the correct way to go about it since you are filtering out other rows you want to check against. I'd use EXISTS for this e.g.
edit: corrected the query
SELECT *
FROM Log L WITH(NOLOCK)
WHERE ProviderId = 48
AND CallType = 'A'
AND Status = 'Success'
AND EXISTS(SELECT * FROM Log WHERE L.SessionId = SessionId AND CallType = 'B' AND Status = 'Failure')
You can essentially filter out rows in the EXISTS part of the query using the aliased Log table (aliased L), matching all rows with the same session ID and seeing if any match the filters you required (failed with call type B)

Group by when joining the same table twice

I'm writing a query to summarize some data. I have a flag in the table that is basically boolean, so I need some sums and counts based on one value of it, and then the same thing for the other value, like so:
select
location
,count(*)
,sum(duration)
from my.table
where type = 'X'
and location = #location
and date(some_tstamp) = #date
group by location
And then the same for another value of the type column. If I join this table twice, how do I still group so I can only get aggregation for each table, i.e. count(a.*) instead of count(*)...
Would it be better to write two separate queries?
EDIT
Thanks everybody, but that's not what I meant. I need to get a summary where type = 'X' and a summary where type = 'Y' separately...let me post a better example. What I meant was a query like this:
select
a.location
,count(a.*)
,sum(a.duration)
,count(b.*)
,sum(b.duration)
from my.table a, my.table b
where a.type = 'X'
and a.location = #location
and date(a.some_tstamp) = #date
and b.location = #location
and date(b.some_tstamp) = #date
and b.type = 'Y'
group by a.location
What do I need to group by? Also, DB2 doesn't like count(a.*), it's a syntax error.
select
location
,Sum(case when type = 'X' then 1 else 0 end) as xCount
,Sum(case when type = 'Y' then 1 else 0 end) as YCount
,Sum(case when type = 'X' then duration else 0 end) as xCountDuration
,Sum(case when type = 'Y' then duration else 0 end) as YCountDuration
from my.table
where
location = #location
and date(some_tstamp) = #date
group by location
This should work in SQL Server. I guess db2 should have something similar.
Edit: Add a where condition to limit the records to select type = X or type = Y, if "type" can have value other than X and Y.
Your example with the join doesn't make a lot of sense. You're doing a Cartesian product between A and B. Is this really what you want?
The following will find count(*) and sum(duration) for each pair that satisfies the WHERE clause. Based on your description, this sounds like what you're looking for:
select
type
,location
,count(*)
,sum(duration)
from my.table
where type IN ('X', 'Y')
and location = #location
and date(some_tstamp) = #date
group by type, location
To make the counts work, instead of count(a.*) just do count(a.location), or any other not-null column (the PK would be ideal).
As to the main question, either of the answers given by shahkalpesh or George Eadon above would work. There is no reason in this example to join the table twice.