Grouping totals by date ranges - sql

I have to get totals from a table using different criteria, which I do like this:
SELECT DISTINCT
SUM(CASE WHEN MYCONDITION1 THEN 1 ELSE 0 END) AS TOTAL1,
SUM(CASE WHEN MYCONDITION2 THEN 1 ELSE 0 END) AS TOTAL2
FROM TABLE1, TABLE2
WHERE COMMON_CONDITION1 AND COMMON_CONDITION2
AND BETWEEN DATE1 AND DATE2;
This works fine and I get the intended result.
Now, I have to repeat this for every week for the last 12 months, excluding holidays period. So, I generate a set of date ranges which will be used in the queries. So, I repeat the above sql statement for all the date ranges, which is a lengthy process.
I have to get the totals for every week. For example from 26-Sep-2010 to 02-Oct-2010, 19-Sep-2010 to 25-Sep-2010, 12-Sep-2010 to 18-Sep-2010, etc.. How should I put those ranges in the query for grouping and in the select list, as I don't have them in a table.
How can I do that in a single shot and get all totals for each date range. Please help me with sql.
Thank you.

You could create a table that contains the date ranges. You can join on the new table; you'll have to replace distinct with group by. For example:
SELECT TABLE3.DATE1
, TABLE3.DATE2
, SUM(CASE WHEN MYCONDITION1 THEN 1 ELSE 0 END) AS TOTAL1
, SUM(CASE WHEN MYCONDITION2 THEN 1 ELSE 0 END) AS TOTAL2
FROM TABLE1, TABLE2, TABLE3
WHERE COMMON_CONDITION1
AND COMMON_CONDITION2
AND DATE_COLUMN BETWEEN TABLE3.DATE1 AND TABLE3.DATE2
GROUP BY
TABLE3.DATE1
, TABLE3.DATE2

Related

Conditional CASE WHEN select snowflake SQL

I am stuck on a conditional snowflake select sql. I am trying to count the IDs when they have the corresponding categorial value. I would appreciate some help.
Thanks
SELECT
YEAR(DATETIME) AS YEAR,
WEEKOVERYEAR(DATETIME) AS WEEK,
COUNT(CASE WHEN ID THEN CATEGORY = 'A')
from table
group by week, year;
Here is one method:
SELECT YEAR(DATETIME) AS YEAR,
WEEKOVERYEAR(DATETIME) AS WEEK,
SUM(CASE WHEN CATEGORY = 'A' THEN 1 ELSE 0 END) as num_a
FROM table
GROUP BY week, year;
Snowflake supports COUNT_IF:
Returns the number of records that satisfy a condition.
Aggregate function
COUNT_IF( <condition> )
SELECT YEAR(DATETIME) AS YEAR,
WEEKOVERYEAR(DATETIME) AS WEEK,
COUNT_IF(CATEGORY = 'A') AS num_a
FROM tab
GROUP BY week, year;
You should / can use IFF() since case when is more suitable when there are multiple conditions.
SELECT
YEAR(DATETIME) AS YEAR,
WEEKOVERYEAR(DATETIME) AS WEEK,
COUNT(IFF(CATEGORY = 'A',ID,NULL)) as count
from table
group by week, year;
COUNT() counts the number of rows that are not null.
If you are want when ID is not null AND CATEGORY = 'A' then
COUNT(CASE WHEN ID IS NOT NULL AND CATEGORY = 'A' THEN TRUE ELSE NULL END)
will give you that, or you can use a SUM like in Gordon's answer
SUM(CASE WHEN ID IS NOT NULL AND CATEGORY = 'A' THEN 1 ELSE 0 END)
or you can use the snowflake IFF as a shorter form for the same thing, which is how I do it
SUM( IFF( ID IS NOT NULL AND CATEGORY = 'A', 1, 0))

How can one count total records AND separately count records where two fields are equal

Let say I have the following table called VISITS:
I need to count the total records for each location, and then have a separate count of those records where Date1 and Date2 values are equal. The final results should look like this:
I can get a count of total using:
select Location, Count(*) as 'Total Visits' from Visits Group by Location
And I can get a count of visits that match by doing
select Location, Count(*) as 'Total Matched' From Visits
where Date1 = Date2 group by Location
But I don't know how to do both counts with a single query.
Use conditional aggregation:
select v.Location, Count(*),
sum(case when v.date1 = v.date2 then 1 else 0 end) as same_day
from Visits v
group by v.location;
Note that your queries are missing the group by clause.
a simple way could be
select Location, Count(*), sum(case when Date1 = Date2 then 1 else 0 end)
from Visits
group by location

Subtract two value by difference criteria in same row

In this table we see different transaction in same date some of Transaction Dr and some transaction Cr. I need Cr - Dr as Transaction Amount per date.
Please see screenshot 1st Table
Result will be-
Result
you could use a case when and group by
select date, sum(case when drcr = 'CR' then amount
when drcr = 'DR' then -amount
else 0 end)
from my_table
group by date
as #scaisEdge but you need a sum.
select date, sum(case when drcr = 'CR' then amuont else (-1 * amount) end) as tran_amt
from my_table
group by date
This should be clear, but the way it works is to add credits and substract debits to the total for each date.

How to write this SQL without duplicating the customer?

I have a table that has customers listed every month with and active_indicator. For each customer, I want to pull the active indicator for just two months (Dec 2014 and Dec 2015), but when I write the below code, I get a table where each customer is listed twice. I know I can do another step to roll up the table to the customer level using max, but is there anyway to do this in one simple SQL query?
select distinct
customer
,case when date='2015-12-01' then active_indicator else 0 end as Dec2015_active_ind
,case when date='2014-12-01' then active_indicator else 0 end as Dec2014_active_ind
from monthly_account_cust
where date in ('2015-12-01', '2014-12-01')
order by customer
Pretty sure you are looking for something like this.
select
customer
, max(case when date = '2015-12-01' then active_indicator else 0 end) as Dec2015_active_ind
, max(case when date = '2014-12-01' then active_indicator else 0 end) as Dec2014_active_ind
from monthly_account_cust
where date in ('2015-12-01','2014-12-01')
group by customer
order by customer

Query from same table to extract different data

In a single table I have 3 columns. First defines a sector, second count and third amount. I need to extract 5 columns of data in the following manner. First column sector. Second and third to contains the values were amount is less than count and third and four to display were amount is more than count in the specific sectors. How should my query look?
Sample Data - 4 row data for sector one.
1,23,44
1,20,15
1,50,45
1,30,20
Result should be
1,100,80,23,44
You can get it done using a GROUP BY and SUM() aggregate function along with CASE statement like
SELECT sector,
SUM(case when count > amount then count else 0 end) as count1,
SUM(case when amount < count then amount else 0 end) as amount1,
SUM(case when count < amount then count else 0 end) as count2,
SUM(case when amount > count then amount else 0 end) as amount2
FROM mytable
GROUP BY sector;