How to use two where conditions in SQL? - sql

Following is the query I have written and I need to where conditions.
Admin_Level_3_palika is not null
Year = '2021'
However, the following query is still giving me null values for Admin_Level_3_palika
SELECT
Admin_Level_3_palika,
COUNT(CASE WHEN Week_number = '21' THEN 1 END) AS count_Week_21,
COUNT(CASE WHEN Week_number = '22' THEN 1 END) AS count_Week_22,
(COUNT(CASE WHEN Week_number = '22' THEN 1 END) -
COUNT(CASE WHEN Week_number = '21' THEN 1 END)) AS Difference
FROM `interim-data.casedata.Interim Latest`
where Admin_Level_3_palika is not null or YEAR = '2021'
GROUP BY
Admin_Level_3_palika
ORDER BY
count_Week_22 desc limit 20
Please help me with how to work with this. Following is an example of my dataset, Epid_ID being unique for each row.
Admin_Level_3_palika Week_number YEAR Epid_ID
Lamkichuha MC 21 2020 COV-NEP-PR5-RUP-20-00022
Lamkichuha MC 21 2021 COV-NEP-PR5-RUP-20-00023

If these are your conditions:
1. Admin_Level_3_palika is not null
2. Year = '2021'
Then you need and:
where Admin_Level_3_palika is not null and Year = '2021'
If year is an integer (as I would expect it to be), drop the single quotes. Don't mix data types in comparisons.
For performance, you might also want to limit the week number:
where Admin_Level_3_palika is not null and
Year = '2021' and
week_number in ('21', '22')
And finally, BigQuery offers countif() which I recommend:
SELECT Admin_Level_3_palika,
COUNTIF(Week_number = '21') AS count_Week_21,
COUNTIF(Week_number = '22') AS count_Week_22,
(COUNTIF(Week_number = '22') - COUNTIF(Week_number = '21')) AS Difference
FROM `interim-data.casedata.Interim Latest`
WHERE Admin_Level_3_palika is not null AND
YEAR = '2021' AND
week_number IN ('21', '22')
GROUP BY Admin_Level_3_palika
ORDER BY count_Week_22 desc
LIMIT 20

change the or to and
the line:
where Admin_Level_3_palika is not null or YEAR = '2021'
should be:
where Admin_Level_3_palika is not null AND YEAR = '2021'
if year is not of type string you can do
where Admin_Level_3_palika is not null AND YEAR = 2021

Related

Calculate difference of data in respective weeks using week number

My data is stored in Google Big QUery in a database. This is how my table looks like. Here Epid_ID is unique for each row and the count is calculated using this value.
Admin_Level_2_district WeekNumber Epid_ID
Jhapa 18 COV-NEP-PR1-SUN-20-00072
Jhapa 19 COV-NEP-PR1-SUN-20-00073
Morang 18 COV-NEP-PR1-SUN-20-00074
Morang 19 COV-NEP-PR1-SUN-20-00075
I want to find the difference in data in two weeks. This is my expected output.
Admin_Level_2_district count_Week_18 count_Week 19 Difference
Jhapa 50 60 10
Morang 60 50 -10
Following is the query I have tried.
SELECT
Admin_Level_2_district,
Week_number,
count(Epid_ID)
FROM `interim-data.casedata.Interim EpiData`
GROUP BY
Admin_Level_2_district,
Week_number
HAVING Week_number = '18'
or Week_number = '19'
Please help!
I think you want conditional aggregation here:
SELECT
Admin_Level_2_district,
COUNT(CASE WHEN WeekNumber = 18 THEN 1 END) AS count_Week_18,
COUNT(CASE WHEN WeekNumber = 19 THEN 1 END) AS count_Week_19,
COUNT(CASE WHEN WeekNumber = 19 THEN 1 END) -
COUNT(CASE WHEN WeekNumber = 18 THEN 1 END) AS Difference
FROM `interim-data.casedata.Interim EpiData`
GROUP BY
Admin_Level_2_district;
You want to use conditional aggregation. In BigQuery, I would recommend countif():
SELECT Admin_Level_2_district,
COUNTIF(week_number = '18') as count_week_18,
COUNTIF(week_number = '19') as count_week_19,
COUNTIF(week_number = '19') - COUNTIF(week_number = '18') as diff
FROM `interim-data.casedata.Interim EpiData`
WHERE Week_number IN ('18', '19')
GROUP BY Admin_Level_2_district;
Note: I would expect week_number to be a number, in which case you would not use single quotes. However, your code treats that as a string, so I left that in.

SQL query overlapping time undercounting

I am writing a query that counts how many people were 18 months active on a certain day of each year.
The problem I'm having is that between the years there is an overlap in time period which causes the later years to be undercounted because they are classified as the previous year.
For example, '2017-03-06' could be considered activity for 2018 AND 2017.
Here is my query:
select case when deposit_dt between '2017-02-07' and date then '2018'
when deposit_dt between '2016-02-07' and '2017-08-07' then '2017'
when deposit_dt between '2015-02-07' and '2016-08-07' then '2016'
when deposit_dt between '2014-02-07' and '2015-08-07' then '2015'
when deposit_dt between '2013-02-07' and '2014-08-07' then '2014'
end as yr, count(unique(op_id))
from activity_table
where deposit_dt between '2013-02-07' and date
group by deposit_dt
Any advice on how to get around this issue (other than running a new query for each year)?
My feeling is that you really want something along the lines of the following:
select
count(case when deposit_dt between '2017-02-07' and date then 1 end) as 2018,
count(case when deposit_dt between '2016-02-07' and '2017-08-07' then 1 end) as 2017,
count(case when deposit_dt between '2015-02-07' and '2016-08-07' then 1 end) as 2016,
count(case when deposit_dt between '2014-02-07' and '2015-08-07' then 1 end) as 2015,
count(case when deposit_dt between '2013-02-07' and '2014-08-07' then 1 end) as 2014
from activity_table
where deposit_dt between '2013-02-07' and date;
Note that it doesn't make sense to group by deposit_dt, since this is the column which is being used to aggregate.
This assumes that you don't have logic beyond this to take the potentially overlapping dates into account. If you can provide logic for how to resolve a date which matches more than one range, then the above query can be updated.
I think this might be what you want.
select count(distinct [2018Users]) as [2018], count(distinct [2017Users]) as [2017],count(distinct [2016Users]) as [2016]
from(
select case when deposit_dt between '2017-02-07' and date then op_id end as [2018Users],
case when deposit_dt between '2016-02-07' and '2017-08-07' then op_id end as [2017Users],
case when deposit_dt between '2015-02-07' and '2016-08-07' then op_id end as [2016Users]
from activity_table
) c

SQL sum with a condition

I have a query that need to have a sum up value, but in one of my table's column, there's an increment and decrements value.
For decremented value, the value of it need to be as negative even it is stored as positive value in the table.
While for incremented value, it remains as positive.
My query look like this:
SELECT
SUM(
CASE WHEN ACTIVITY_TYPE = '0' THEN -(ACTIVITY_VALUE)
ELSE ACTIVITY_VALUE
END
) AS NEW_ACTIVITY_VALUE
FROM V_EMPLOYEE_PAYACT
WHERE ACTIVITY_TYPE IN ('0','1')
AND EMPLOYEE_NO = '00002789'
AND ((YEAR = 2014 AND MONTH <= 4)
OR
(YEAR > 2013 AND YEAR <2014)
OR
(YEAR = 2013 AND MONTH >= 5))
GROUP BY YEAR, MONTH
It return this result:
NEW_ACTIVITY_VALUE
391.00
-600.00
I need the value to be as -209 (the total of those two number)
You are currently grouping the sum per unique combination of month and year. If you want the total sum, just drop the group by clause:
SELECT
SUM(
CASE WHEN ACTIVITY_TYPE = '0' THEN -(ACTIVITY_VALUE)
ELSE ACTIVITY_VALUE
END
) AS NEW_ACTIVITY_VALUE
FROM V_EMPLOYEE_PAYACT
WHERE ACTIVITY_TYPE IN ('0','1')
AND EMPLOYEE_NO = '00002789'
AND ((YEAR = 2014 AND MONTH <= 4)
OR
(YEAR > 2013 AND YEAR <2014)
OR
(YEAR = 2013 AND MONTH >= 5))
Try this one:
SELECT
SUM(
CASE
WHEN ACTIVITY_TYPE = '0' THEN
- (ACTIVITY_VALUE)
ELSE
ACTIVITY_VALUE
END
) AS NEW_ACTIVITY_VALUE
FROM
V_EMPLOYEE_PAYACT
WHERE
ACTIVITY_TYPE IN ('0', '1')
AND EMPLOYEE_NO = '00002789'
AND (
(YEAR = 2014 AND MONTH <= 4)
OR (YEAR > 2013 AND YEAR < 2014)
OR (YEAR = 2013 AND MONTH >= 5)
)

calculate YTD & Prev Year YTD

I want to calculate YTD (1st Jan 2016 to last date of a month) & Prev year YTD (1st Jan 2015 to last date of a month) for each Client.
Below is the SQL Query that i have attempted, but here i get two rows for each Client instead of 1 as I'm using 'CASE WHEN'.
My question is how can i get the result in just one row per Client instead of one row for YTD & another row for YTD-1 for each client?
SELECT [ClientName]
, (CASE WHEN YEAR([Purchase_Date]) = YEAR(GETDATE())-1 THEN (count(Activity)) end) AS 'YTD-1'
, (CASE WHEN YEAR([Purchase_Date]) = YEAR(GETDATE()) THEN (count(Activity)) end) AS 'YTD'
FROM Purchases
WHERE MONTH([Purchase_Date]) <= MONTH(GETDATE())
GROUP BY [ClientName], YEAR([Purchase_Date])
ORDER BY 1
Kindly Help!
Thanks,
Ramesh
Remove YEAR([Purchase_Date]) from the GROUP BY part.
Also, instead of:
(CASE WHEN YEAR([Purchase_Date]) = YEAR(GETDATE())-1 THEN (count(Activity)) end) AS 'YTD-1'
use:
count(CASE WHEN YEAR([Purchase_Date]) = YEAR(GETDATE())-1 THEN Activity else NULL end) AS 'YTD-1'
And the same for 'YTD' column.

Limit SQL query to days

I use this SQL query to make status report by day:
CREATE TABLE TICKET(
ID INTEGER NOT NULL,
TITLE TEXT,
STATUS INTEGER,
LAST_UPDATED DATE,
CREATED DATE
)
;
Query:
SELECT t.created,
COUNT(CASE WHEN t.status = '1' THEN 1 END) as cnt_status1,
COUNT(CASE WHEN t.status = '2' THEN 1 END) as cnt_status2,
COUNT(CASE WHEN t.status = '3' THEN 1 END) as cnt_status3,
COUNT(CASE WHEN t.status = '4' THEN 1 END) as cnt_status4
FROM ticket t
GROUP BY t.created
How I can limit this query to last 7 days?
Also I would like to get the results split by day. Fow example I would like to group the first dates for 24 hours, second for next 24 hours and etc.
Expected result:
This might help:
SELECT TO_CHAR(t.created, 'YYYY-MM-DD') AS created_date,
COUNT(CASE WHEN t.status = '1' THEN 1 END) as cnt_status1,
COUNT(CASE WHEN t.status = '2' THEN 1 END) as cnt_status2,
COUNT(CASE WHEN t.status = '3' THEN 1 END) as cnt_status3,
COUNT(CASE WHEN t.status = '4' THEN 1 END) as cnt_status4
FROM ticket t
WHERE t.created >= SYSDATE-7
GROUP BY TO_CHAR(t.created, 'YYYY-MM-DD')
ORDER BY created_date;
I used the oracle function for date conversion. I'm sure you'll find the corresponding one for postgresql.