Aggregate two value when a condition is met - sql

Edit: I need to partition by ID and Month
I have the table below:
TableA1 50 low 201803 20
I would like to multiple hoursxWorkingDaysInMonth when Cat = 'low'.
ID Hours Cat Month WorkingDaysInMonth
I have the SQL below, but it doesn't account for the condition
SELECT SUM(HOURS * MONTH) OVER (PARTITION BY ID, MONTH) AS TESTING,
FROM TABLEA

You would seem to want:
SELECT SUM(A.HOURS * A.WORKINGDAYSINMONTH) AS AMT
FROM TABLEA A
WHERE cat = 'low';
If you want the logic on each row:
select a.*,
(case when a.cat = 'low' then a.hour * a.workingdaysinmonth end) as amt
from tablea a;

SELECT CASE WHEN cat = 'low' THEN HOURS * WORKINGDAYSINMONTH END AS AMT
FROM TABLEA
SELECT DECODE(CAT,'low',HOURS * WORKINGDAYSINMONTH END) AS AMT
FROM TABLEA
You can use a CASE or DECODE statement to do this work.
In case if you want to add a default to the rest of the rows you can have else statement in your query like this
SELECT CASE WHEN cat = 'low' THEN HOURS * WORKINGDAYSINMONTH
ELSE 0 END AS AMT
FROM TABLEA

Related

Finding records in column A that match 3 out of 4 records in column B SQL

Above is sample data illustrating my question.
What I am trying to achieve is to find all the products in column A that are stored in warehouses BB, CC, and so on but are missing in AA which is a master warehouse. To determine which products need to be added to the master warehouse.
I would greatly appreciate the help.
Maybe a query like below will help
select distinct fruits
from yourtable T
where warehouse <> 'AA'
and not exists (
select 1
from yourtable YT
where YT.warehouse = 'AA' and YT.fruits = T.fruits
)
If you want just the fruit that is missing, you can use aggregation with a having clause:
select fruit
from t
group by fruit
having sum(case when warehouse = 'AA' then 1 else 0 end) = 0;
If you want the complete rows, then not exists is one approach:
select t.*
from t
where not exists (select 1
from t t2
where t2.fruit = t.fruit and t2.warehouse = 'AA'
);
I'd use the not exists operator:
SELECT DISTINCT fruits
FROM mytable a
WHERE NOT EXSITS (SELECT *
FROM mytable b
WHERE a.fruits = b.fruits AND
b.warehouse = 'AA')

Joining two different queries under one answer

I have two different queries that have produced the correct result, but I would like to have them produce the answer out in one table. How do I do that?
Here is my code:
SELECT count(distinct ID) as NoOfEmployees
FROM Table_Name
WHERE date<= '2012-05-31';
select count(subA.ID) as EmployeesChanged from (
SELECT A.ID
FROM Table_Name A
WHERE A.date < '2012-06-01'
GROUP BY 1
HAVING COUNT(A.Service_type) > 1 ) subA
Currently I have the following output:
Number of Employees
x
Employees Changed
x
How do I make it
Number of Employees | Employees Changed | (Number of employees - number changed)
x | x | x
I don't know what database do you use. But for some databases you can try:
select q1.Value, q2.Value, q1.Value - q2.Value from
(SELECT count(distinct ID) as Value FROM Table_Name
WHERE date<= '2012-05-31') q1,
(select count(subA.ID) as Value from
( SELECT A.ID FROM Table_Name A
WHERE A.date < '2012-06-01' GROUP BY 1
HAVING COUNT(A.Service_type) > 1 ) subA) q2
If date<= '2012-05-31' is the same as A.date < '2012-06-01' ?
SELECT COUNT(1) AS NoOfEmployees,
SUM(CASE WHEN STCount > 0 then 1 else 0 end) as HasChange,
SUM(CASE WHEN STCount = 0 then 1 else 0 end) as NoChange
FROM
(SELECT ID,
COUNT(A.Service_type) STCount
FROM Table_Name
WHERE date<= '2012-05-31'
GROUP BY ID) AS Data
You can use CROSS JOIN:
SELECT a.*, b.*, a.NoOfEmployees - b.EmployeesChanged
FROM
(
SELECT count(distinct ID) as NoOfEmployees
FROM Table_Name
WHERE date<= '2012-05-31'
) a
CROSS JOIN
(
SELECT count(subA.ID) as EmployeesChanged
FROM
(
SELECT A.ID
FROM Table_Name A
WHERE A.date < '2012-06-01'
GROUP BY 1
HAVING COUNT(A.Service_type) > 1
) subA
) b
Edit:
You might be able to greatly optimize your query by using conditional aggregation instead of executing two separate queries:
SELECT a.NoOfEmployees, a.EmployeesChanged, a.NoOfEmployees - a.EmployeesChanged
FROM
(
SELECT
COUNT(DISTINCT CASE WHEN date <= '2012-05-31' THEN ID END) as NoOfEmployees,
COUNT(DISTINCT CASE WHEN date < '2012-06-01' AND COUNT(Service_type) > 1 THEN ID END) AS EmployeesChanged
FROM Table_Name
GROUP BY ID
) a

Multiple where clauses in one row sql

I want to take the below statement and fuse it into one query.
SELECT COUNT(*) AS count1 WHERE Month='11' AND Flag = 1
SELECT COUNT(*) AS count2 WHERE Month='11' AND Flag = 2
SELECT COUNT(*) AS count1 WHERE Month='12' AND Flag = 1
SELECT COUNT(*) AS count2 WHERE Month='12' AND Flag = 2
I want this to display as one query with columns count1 and count2 and rows month 11 and month 12.
Is there a syntax for this?
You can combine SUM and CASE to get various counts in one go:
SELECT
Month,
SUM(CASE WHEN Flag=1 THEN 1 ELSE 0 END) as count1,
SUM(CASE WHEN Flag=2 THEN 1 ELSE 0 END) as count2
from
...
WHERE Month in ('11','12')
GROUP BY
Month /* Other columns? */
With two columns only, it can be something like this:
select
(SELECT COUNT(*) FROM tablename WHERE Month='11' AND Flag = 1) as 'count1'
(SELECT COUNT(*) FROM tablename WHERE Month='11' AND Flag = 2) as 'count2'
UNION ALL
select
(SELECT COUNT(*) FROM tablename WHERE Month='12' AND Flag = 1),
(SELECT COUNT(*) FROM tablename WHERE Month='12' AND Flag = 2)
Replace tablename with the name of your table.
How about this:
select
month, flag, count(*)
from
table
where
month in ('11', '12') and
flag in (1, 2)
group by
month, flag;

Merge two SELECT queries into one

I have two queries where I only need the count of total records but the only difference in the queries is one field value.
Example;
SELECT COUNT(*) AS group_a
FROM tbl
WHERE category = 'value_a'
SELECT COUNT(*) AS group_b
FROM tbl
WHERE category = 'value_b'
How can I get something like this: (pseudo)
SELECT COUNT(*) AS group_a, COUNT(*) AS group_b
FROM tbl
WHERE category IN ('value_a', 'value_b')
But the results are like this
group_a , group_b
56, 101
I was thinking a CASE statement in the query to filter the two but how do I implement it? or is there a better way?
I'm doing a UNION right now but wanted to know if I could return one record with two results
select sum(case when category = 'value_a' then 1 else 0 end) as group_a,
sum(case when category = 'value_b' then 1 else 0 end) as group_b
from tbl
where category in ('value_a', 'value_b')
select sum(case when category = 'value_a' then 1 else 0 end) group_a,
sum(case when category = 'value_b' then 1 else 0 end) group_b
from tbl
SELECT category,COUNT(*) FROM tbl
GROUP BY category;
That expands to more categories. If you want just those categories
SELECT category,COUNT(*) FROM tbl
WHERE category IN ('value_a', 'value_b')
GROUP BY category;
What strange answers for counting. Here's a straightforward COUNT:
SELECT COUNT(category = 'value_a' OR NULL) AS group_a, COUNT(category = 'value_b' OR NULL) AS group_b FROM tbl;
The COUNT aggregate in PostgreSQL allows complex syntax like I've shown. Note that the OR NULL is quite essential as COUNT counts only those rows for which the condition category = '...' OR NULL gives non-NULL answer.
Just for the fun of it:
SELECT *
FROM
(
SELECT category
FROM tbl
) subquery
PIVOT
(
COUNT(category)
FOR category IN ([value_a],[value_b])
) AS piv

SQL Select for multiple where clause

I am trying to create SQL Select that returns counts of a certain field based on a field.
So, here is what I am trying to do.
Select count(distinct id) as TotalCount, -- this will be the total of id
count(distinct id where type='A') as TotalA, -- this will be total when type='A'
count(distinct id where type='B') as TotalB -- This will be total when type = 'B'
from MyTable
Basically, TotalCount = TotalA + TotalB.
How can I achieve this in SQL Select Statement?
Thanks.
Select count(distinct id) as TotalCount, -- this will be the total of id
count(distinct case type when 'A' then id else NULL end) as TotalA,
count(distinct case type when 'B' then id else NULL end) as TotalB
from MyTable;
Of course TotalCount may or may not be TotalA + TotalB, depending on the actual data.
You can do it like that:
SELECT
count(distinct id) as TotalCount,
sum(CASE WHEN type = 'A' THEN 1 ELSE 0) as TotalA,
sum(CASE WHEN type = 'B' THEN 1 ELSE 0) as TotalB,
FROM
MyTable
Count per type:
SELECT
type,
count(DISTINCT id)
FROM
MyTable
GROUP BY
type
Why not simply UNION the separate queries.
Select 'all' as which, count(distinct id) as Total from mytable
union
select 'a' as which, count(distinct id) where type='A' as Total from mytable
union
select 'b' as which, count(distinct id) where type='B' as Total from mytable