Need to count only once in case statement - sql

I need to count only 1 even if condition is met for other records as well
using case statement to check condition
sample data
table a
meeting_id
1
table b
**meeting_id | attendee_id**
1, 10
1, 11
1, 12
1, 13
table c
**attendee_id | dept**
10, field sales
11, field sales
12, dmt
13, field sales
select A.ACC_ID,
TO_NUMBER(SUBSTRING(A.MONTH_NO,1,4)) AS YY,
TO_NUMBER(SUBSTRING(A.MONTH_NO,5,6)) AS MM,
sum(case when USER_INFO.DEPARTMENT='Field Sales' then 1 else 0 end) AS MEETING_WITH_SALE
from "TABLE1" A LEFT JOIN "TABLE2" B
ON (A.meeting_id=A.meeting_id) AND (TO_NUMBER(SUBSTRING(A.MONTH_NO,1,4))=YEAR(A.DATE_OF_MEETING)) AND (TO_NUMBER(SUBSTRING(A.MONTH_NO,5,6))=MONTH(A.DATE_OF_MEETING))
LEFT JOIN "TABLE3" c ON A.attendee_id=c.attendee_id
GROUP BY 1,2
expected result
meeting id 1 has 1 sales meeting because one/more of its attendee's are from sales dept

you have multiple options:
1) get a boolean saying whether the sum was 1 or higher, and convert it to int:
(sum(case when USER_INFO.DEPARTMENT='Field Sales' then 1 else 0 end)>=1)::int)
2) use least function:
least(1,sum(case when USER_INFO.DEPARTMENT='Field Sales' then 1 else 0 end))
3) use another case statement:
case
when sum(case when USER_INFO.DEPARTMENT='Field Sales' then 1 else 0 end)>1
then 1
else 0
end
overall, it's just piping the aggregate that you had into scalar post-processing

Related

SQL query issue COUNT()

I tried set the count of rows which have a specific value for multiple columns in the same query
this is what I have tried...
SELECT
COUNT(*) AS house_with_12_rooms,
COUNT(*) AS house_with_4_rooms
FROM housetable
WHERE num_of_rooms = "twelve"
OR num_of_rooms = "four"
since there are 157 rows with houses with 12 rooms and 1 row with houses with 4 rooms the result adds up the counts in the result table RATHER THAN placing 157 and 1 respectively.
Row house_with_12_rooms house_with_4_rooms
1 158 158
Could someone give me a clue on how to set up the query properly?
Use conditional aggregation:
SELECT SUM(CASE WHEN num_of_rooms = 'twelve' THEN 1 ELSE 0 END) AS house_with_12_rooms,
SUM(CASE WHEN num_of_rooms = 'four' THEN 1 ELSE 0 END) AS house_with_4_rooms
FROM housetable
WHERE num_of_rooms IN ('twelve', 'four')

SQL to calculate Net Capacity

How to write a SQL to get the Net change in capacity by using the capacity (when status is 1 or 2) and minus the total capacity (when status is 3) for each month? Thanks. Here is the table:
STATUS MONTH CAPACITY
1 01/16 5
3 01/16 2
1 02/16 11
3 02/16 20
1 03/16 8
3 03/16 12
1 04/16 4
2 04/16 10
3 04/16 18
2 05/16 14
3 05/16 37
2 06/16 4
3 06/16 8
For example, the net change in capacity for Jan. 16 is 5 minus 2 equals 3.
You need a conditional sum:
SUM(CASE WHEN STATUS IN (1,2) THEN CAPACITY ELSE 0 END) -
SUM(CASE WHEN STATUS IN (3) THEN CAPACITY ELSE 0 END)
dnoeth answer can be simplified to
SUM(CASE WHEN STATUS IN (1,2) THEN CAPACITY WHEN STATUS IN (3) THEN -CAPACITY ELSE 0 END)
Builds on 1,2 < 3
select MONTH, [Net change]=SUM(CASE STATUS/3 WHEN 0 THEN CAPACITY ELSE -CAPACITY END)
from t
group by MONTH;
no CASE statement:
select month, sum(capacity)-2*sum((status/3)*capacity) from table group by month;
Here is an example
You can join the table to itself and perform the calculation like so:
SELECT
a.status,
a.month,
a.capacity,
b.capacity AS total_capacity,
a.capacity - b.capacity AS net_capacity
FROM
table a
JOIN
table b
ON (a.month = b.month)
AND (b.status = 3)
WHERE
a.status IN (1,2);
-- If you don't want to have the status and instead aggregate in the event there are two within the same month:
SELECT
a.month,
SUM(a.capacity) AS capacity,
SUM(b.capacity) AS total_capacity,
SUM(a.capacity) - MAX(b.capacity) AS net_capacity
FROM
table a
JOIN
table b
ON (a.month = b.month)
AND (b.status = 3)
WHERE
a.status IN (1,2)
GROUP BY
a.month;
SELECT
"Status",
"Month",
SUM(Capacity) AS Capacity
FROM ( SELECT
"Status",
"Month",
CASE WHEN Status = 3 THEN -1 * Capacity ELSE Capacity END AS Capacity FROM tbl
) t
GROUP BY
"Status",
"Month"

Count in sql with group by

Table name: mytable
Id username pizza-id pizza-size Quantity order-time
--------------------------------------------------------------
1 xyz 2 9 2 09:00 10/08/2014
2 abc 1 11 3 17:45 13/07/2014
This is mytable which has 6 columns. Id is int, username is varchar, order-time is datetime and rest are of integer datatype.
How to count the number of orders with the following pizza quantities: 1, 2, 3, 4, 5, 6,7 and above 7?
Using a T-SQL query.
It would be very helpful If any one could help to me find the solution.
Try this !
SELECT COUNT(ID),CASE WHEN QUANTITY<7 THEN QUANTITY ELSE 'ABOVE7' END AS QUANTITIES
FROM mytable
GROUP BY CASE WHEN QUANTITY<7 THEN QUANTITY ELSE 'ABOVE7' END
Try
Select CASE WHEN Quantity > 7 THEN 'OVER7' ELSE Cast(quantity as varchar) END Quantity,
COUNT(ID) NoofOrders
from mytable
GROUP BY CASE WHEN Quantity > 7 THEN 'OVER7' ELSE Cast(quantity as varchar) END
or
Select
SUM(Case when Quantity = 1 then 1 else 0 end) Orders1,
SUM(Case when Quantity = 2 then 1 else 0 end) Orders2,
SUM(Case when Quantity = 3 then 1 else 0 end) Orders3,
SUM(Case when Quantity = 4 then 1 else 0 end) Orders4,
SUM(Case when Quantity = 5 then 1 else 0 end) Orders5,
SUM(Case when Quantity = 6 then 1 else 0 end) Orders6,
SUM(Case when Quantity = 7 then 1 else 0 end) Orders7,
SUM(Case when Quantity > 7 then 1 else 0 end) OrdersAbove7
from mytable
If the requirement is like count the number of orders with different pizza quantities and represent count of orders as : 1, 2, 3, 4, 5, 6,7 and consider all above order counts in new category : 'above 7' then you can use window function as:
select case when totalorders < = 7 then cast(totalorders as varchar(10))
else 'Above 7' end as totalorders
, Quantity
from
(
select distinct count(*) over (partition by Quantity order by Quantity asc)
as totalorders,
Quantity
from mytable
) T
order by Quantity
DEMO
Edit: if the requirement is like count the number of orders with pizza quantities: 1, 2, 3, 4, 5, 6,7 and consider all other pizza quantities in new category : 'above 7' then you can write as:
select distinct
count(*) over (
partition by Quantity order by Quantity asc
) as totalorders,
Quantity
from (
select
case when Quantity < = 7 then cast(Quantity as varchar(20))
else 'Above 7' end as Quantity, id
from mytable ) T
order by Quantity
DEMO

SQL: Comparing count of 2 fields with specific value

I have 2 tables, one (Jobs) contains the list of the jobs and second contains the details of the records in each job.
Jobs
JobID Count
A 2
B 3
Records
JobID RecordID ToBeProcessed IsProcessed
A A1 1 1
A A2 1 1
B B1 1 1
B B2 1 0
B B3 1 0
How would I be able to create a query that would list all the jobs that have the count of ToBeProcessed which has a value of 1 is equal to the count of isProcessed that has a value of 1? Thanks in advance. Any help is greatly appreciated.
Start with the calculation of the number of items with ToBeProcessed set to 1 or IsProcessed set to one:
SELECT
JobID
, SUM(CASE WHEN ToBeProcessed=1 THEN 1 ELSE 0 END) ToBeProcessedIsOne
, SUM(CASE WHEN IsProcessed=1 THEN 1 ELSE 0 END) IsProcessedIsOne
FROM Records
GROUP BY JobID
This gives you all counts, not only ones where ToBeProcessedIsOne is equal to IsProcessedIsOne. To make sure that you get only the records where the two are the same, use either a HAVING clause, or a nested subquery:
-- HAVING clause
SELECT
JobID
, SUM(CASE WHEN ToBeProcessed=1 THEN 1 ELSE 0 END) ToBeProcessedIsOne
, SUM(CASE WHEN IsProcessed=1 THEN 1 ELSE 0 END) IsProcessedIsOne
FROM Records
GROUP BY JobID
HAVING SUM(CASE WHEN ToBeProcessed=1 THEN 1 ELSE 0 END)=SUM(CASE WHEN IsProcessed=1 THEN 1 ELSE 0 END)
-- Nested subquery with a condition
SELECT * FROM (
SELECT
JobID
, SUM(CASE WHEN ToBeProcessed=1 THEN 1 ELSE 0 END) ToBeProcessedIsOne
, SUM(CASE WHEN IsProcessed=1 THEN 1 ELSE 0 END) IsProcessedIsOne
FROM Records
GROUP BY JobID
) WHERE ToBeProcessedIsOne = IsProcessedIsOne
Note: if ToBeProcessed and IsProcessed are of type that does not allow values other than zero or one, you can replace the CASE statement with the name of the column, for example:
SELECT
JobID
, SUM(ToBeProcessed) ToBeProcessedIsOne
, SUM(IsProcessed) IsProcessedIsOne
FROM Records
GROUP BY JobID
HAVING SUM(ToBeProcessed)=SUM(IsProcessedD)
if im not misunderstanding your question it looks like you just need a WHERE clause in your statement to see when they are both equal to 1.
SELECT
r.JobID AS j_id,
r.RecordID as r_id,
r.ToBeProcessed AS tbp,
r.IsProcessed AS ip
FROM Records AS r
WHERE r.ToBeProcessed = 1 AND r.IsProcessed = 1
GROUP BY j_id;
let me know if this is not what you are asking for.
if its a count from a different table then just do a count of the tbp and ip rows grouped by jobID and then the where should still do the trick

how to substract two sums based on different field values in one table (view)

example: i need the numbers of which the sum of the amount where id = 1 is not equal of the sum of the amount where id <> 1, together with the id's and difference.
The table (view in this case) may look like this:
NUMBER AMOUNT ID
0001 500 1
0001 500 2
0002 400 3
0003 299 1
0003 300 3
0003 300 3
Many thanks for your help on this one.
Using this query you can get sum of amounts grouped by number, with ID equals 1 and ID not equals 1.
SELECT NUMBER
, SUM(CASE WHEN ID = 1 THEN AMOUNT ELSE 0 END) AS Equals1
, SUM(CASE WHEN ID <> 1 THEN AMOUNT ELSE 0 END) AS NotEquals1
FROM DataTable
GROUP BY NUMBER
If this is you expected, use following query to get difference amounts grouped by number.
SELECT NUMBER, (Equals1 - NotEquals1) AS DifferenceAmount
FROM
(
SELECT NUMBER
, SUM(CASE WHEN ID = 1 THEN AMOUNT ELSE 0 END) AS Equals1
, SUM(CASE WHEN ID <> 1 THEN AMOUNT ELSE 0 END) AS NotEquals1
FROM DataTable
GROUP BY NUMBER
) AS GroupedTable
WHERE Equals1 <> NotEquals1
SELECT
MyView.Number,
MyView.Amount - D.OverOneTotal AS Difference
FROM
MyView
LEFT JOIN
(SELECT
Number,
SUM(Amount) OverOneTotal
FROM
MyView
WHERE
ID > 1
GROUP BY
Number) D ON MyView.Number = D.Number
WHERE
MyView.ID = 1
AND MyView.Amount <> D.OverOneTotal