Do several aggregates in one query using where clause SQL - sql

Is it possible to do several aggregate functions inside a single query
I know whe can use
SELECT SUM(value) FROM mytable WHERE date between '2012-05-01' AND '2012-06-01'
I've been trying to make an example
CREATE TABLE mytable
(id varchar(10), value int, `date` date, situation varchar(10) ) ;
INSERT INTO mytable
(id, value, date, situation)
VALUES
('id0', 1338, '2012-05-14','Urgent'),
('id0', 3572, '2012-05-13','Urgent'),
('id0', 3232, '2012-05-06','Urgent'),
('id0', 3068, '2012-05-05','Post'),
('id0', 3363, '2012-05-04','Urgent'),
('id0', 2022, '2012-04-28','Anual'),
('id0', 3193, '2012-04-24','Post')
But is it possible to use the same query to get other aggregate values?
SELECT SUM(value),SUM(value),Count(*) FROM mytable WHERE date between '2012-05-01' AND '2012-06-01', WHERE date between '2012-05-01' AND '2012-10-01', Where situation like 'Urgent'
instead of 3 queries:
SELECT SUM(value) FROM mytable WHERE date between '2012-05-01' AND '2012-06-01'
SELECT SUM(value) FROM mytable WHERE date between '2012-05-01' AND '2012-10-01'
SELECT Count(*) FROM mytable Where situation like 'Urgent'

use case
select
sum(case when date between '2012-05-01' AND '2012-06-01' then value else 0 end) as sum1,
sum(case when date between '2012-05-01' AND '2012-10-01' then value else 0 end) as sum2,
sum(case when situation like 'Urgent' then 1 else 0 end) as count1
from mytable

You can
SELECT
SUM(CASE WHEN date between '2012-05-01' AND '2012-06-01' THEN value ELSE 0 END)
as sum1,
SUM(CASE WHEN date between '2012-05-01' AND '2012-10-01' THEN value ELSE 0 END)
as sum2,
COUNT(CASE WHEN situation like 'Urgent%' THEN 1 ELSE 0 END)
as cnt1
FROM mytable Where situation like 'Urgent%' OR date between '2012-05-01' AND '2012-10-01'
I guess you missed % in like : like 'Urgent%', not like 'Urgent'.

Related

Combine 2 queries together

I am struggling to work out combining a query that should give me 3 columns of Month, total_sold_products and drinks_sold_products
Query 1:
Select month(date), count(id) as total_sold_products
from Products
where date between '2022-01-01' and '2022-12-31'
Query 2
Select month(date), count(id) as drinks_sold_products
from Products where type = 'drinks' and date between '2022-01-01' and '2022-12-31'
I tried the union function but it summed count(id) twice and gave me only 2 columns
Many thanks!
Union is for attaching sets of data on top of each other. You need conditional aggregation or a join. See below.
SELECT MONTH(date),
COUNT(*) AS total_sold_products,
COUNT(CASE WHEN type = 'drinks' THEN 1 ELSE 0 END) AS drinks_sold_products,
FORMAT((CASE
WHEN COUNT(*) > 0 THEN
COUNT(CASE WHEN type = 'drinks' THEN 1 ELSE 0 END)/COUNT(*)
ELSE 0 END),
'P') AS Percentage
FROM Products
WHERE date BETWEEN'2022-01-01' AND '2022-12-31'
GROUP BY MONTH(date)

Count sequence selected columns

I have query below, I want sequence result like the value of 'feb' will sum by jan and feb, value of 'mar' will sum by jan, feb and mar,... . Is there any way to get the result like that?
select A.location as location
, count(Case When SUBSTRING(A.base_date,5,2)='01' Then A.customer_no else null end) as "jan"
, count(Case When SUBSTRING(A.base_date,5,2)='02' Then A.customer_no else null end) as "feb"
....
, count(Case When SUBSTRING(A.base_date,5,2)='12' Then A.customer_no else null end) as "dec"
from table_income A group by A.location;
SQL is a much more effective language when you think in rows rather than columns (normalisation).
For example, having one row per month is much simpler...
SELECT
location,
SUBSTRING(base_date,5,2) AS base_month,
SUM(COUNT(customer_no))
OVER (
PARTITION BY location
ORDER BY SUBSTRING(base_date,5,2)
)
AS count_cust
FROM
table_income
GROUP BY
location,
SUBSTRING(base_date,5,2)
Side notes:
If your base_date is a string, it shouldn't be, use data-types relevant to the data
If your base_date is a date or timestamp, you should really use date/timestamp functions, such as EXTRACT(month FROM base_date).
You probably should also account for different years...
SELECT
location,
DATE_TRUNC('month', base_date) AS base_month,
SUM(COUNT(customer_no))
OVER (
PARTITION BY location, DATE_TRUNC('year', base_date)
ORDER BY DATE_TRUNC('month', base_date)
)
AS count_cust
FROM
table_income
GROUP BY
location,
DATE_TRUNC('month', base_date)
Try this :
SELECT A.location as location
, count(Case When SUBSTRING(A.base_date,5,2) in ('01') Then A.customer_no else null end) as "jan"
, count(Case When SUBSTRING(A.base_date,5,2) in ('01','02') Then A.customer_no else null end) as "feb"
....
, count(Case When SUBSTRING(A.base_date,5,2) in ('01','02',...'12') Then A.customer_no else null end) as "dec"
from table_income A group by A.location;

MSSQL Group by and Select rows from grouping

I'm trying to figure out if what I'm trying to do is possible. Instead of resorting to multiple queries on a table, I wanted to group the records by business date and id then group by the id and select one date for a field and another date for the other field.
SELECT
*
{AMOUNT FROM DATE}
{AMOUNT FROM OTHER DATE}
FROM (
SELECT
date,
id,
SUM(amount) AS amount
FROM
table
GROUP BY id, date
AS subquery
GROUP BY id
It seems that you're looking to do a pivot query. I usually use cross tabs for this. Based on the query you posted, it could look like:
SELECT
id,
SUM(CASE WHEN date = '20190901' THEN amount ELSE 0 END) AmountFromSept01,
SUM(CASE WHEN date = '20191001' THEN amount ELSE 0 END) AmountFromOct01
FROM (
SELECT
date,
id,
SUM(amount) AS amount
FROM
table
GROUP BY id, date
)AS subquery
GROUP BY id;
You could also use a CTE.
WITH CTE AS(
SELECT
date,
id,
SUM(amount) AS amount
FROM
table
GROUP BY id, date
)
SELECT
id,
SUM(CASE WHEN date = '20190901' THEN amount ELSE 0 END) AmountFromSept01,
SUM(CASE WHEN date = '20191001' THEN amount ELSE 0 END) AmountFromOct01
FROM CTE
GROUP BY id;
Or even be a rebel and do the operation directly.
SELECT
id,
SUM(CASE WHEN date = '20190901' THEN amount ELSE 0 END) AmountFromSept01,
SUM(CASE WHEN date = '20191001' THEN amount ELSE 0 END) AmountFromOct01
FROM CTE
GROUP BY id;
However, some people have tested for performance and found that pre-aggregating can improve performance.
If I understand you correctly, then you're just trying to pivot, but only with two particular dates:
select id,
date1 = sum(iif(date = '2000-01-01', amount, null)),
date2 = sum(iif(date = '2000-01-02', amount, null))
from [table]
group by id

How to group data by different date period in sql?

How to group data by different date period in sql?
For example, I want the data to be grouped from 1/2/2015 to 6/2/2015, 7/2/2015 to 12/2/2015 etc. So far I could only group them according to 1 date range by using the WHERE condition.
SELECT type, count(*)
from table1
WHERE Day(datefield) <=6
Group by type
table1:
type, datefield
typeA, '2015-2-1'
typeB, '2015-2-2'
typeB, '2015-2-9'
typeA, '2015-2-18'
typeB, '2015-2-28'
desired result:
type, no. for day 1-6, no. for day 7-12, no. for day 13-18, no. for day 19-24, no. for day 25-31
type A, 1, 0, 1, 0, 0
type B, 1, 1, 0, 0, 1
First create a derived table where each datefield is replaced by a label ('1-6','7-12',etc.).
Then group that table by its label and type and get the counts. Finally pivot the labels into columns
using conditional aggregation (max(case when ...).
select type,
max(case when date_label = '1-6' then date_count end) '1-6',
max(case when date_label = '7-12' then date_count end) '7-12',
max(case when date_label = '13-18' then date_count end) '13-18',
max(case when date_label = '19-24' then date_count end) '19-24',
max(case when date_label = '25-31' then date_count end) '25-31',
from (
select
type,
date_label,
count(*) date_count
from
(select type,
case when day(datefield) <=6 then '1-6'
when day(datefield) <= 12 then '7-12'
when day(datefield) <= 18 then '13-18'
when day(datefield) <= 24 then '19-24'
when day(datefield) <= 31 then '25-31'
else 'n/a' end as date_label
from table1) t1
group by type, date_label
) t1 group by type

translate aggregate SQL query with case and When to MS Access

I have executed with no problem the query in SQL but it does not work in Access
Case is not avaliable in Access right, so IIf must be used...
select
sum(case when date between '2012-05-01' AND '2012-06-01' then value else 0 end) as sum1,
sum(case when date between '2012-05-01' AND '2012-10-01' then value else 0 end) as sum2,
sum(case when situation like 'Urgent' then 1 else 0 end) as urgent,
sum(case when situation like 'Anual' then 1 else 0 end) as anual,
sum(1) as total
from mytable
Is there a better way of doing this?
Will this query work?
select
sum(IIf date between '2012-05-01' AND '2012-06-01',value,0) as sum1,
sum(IIf date between '2012-05-01' AND '2012-10-01',value,0) as sum2,
sum(IIf situation like 'Urgent',1,0 ) as urgent,
sum(IIf situation like 'Anual' ,1,0 ) as anual,
sum(1) as total
from mytable
You need parentheses for IIf() as in IIf(expression, truepart, falsepart)
Enclose date and value in square brackets because both are reserved words.
Your Like comparisons didn't include any pattern matching, so I substituted = instead.
I assumed date is Date/Time data type, so enclosed the values with the # delimiter.
SELECT
Sum(IIf([date] BETWEEN #2012-05-01# AND #2012-06-01#,[value],0)) AS Sum1,
Sum(IIf([date] BETWEEN #2012-05-01# AND #2012-10-01#,[value],0)) AS Sum2,
Sum(IIf(situation = 'Urgent',1,0 )) AS urgent,
Sum(IIf(situation = 'Anual' ,1,0 )) AS anual,
Sum(1) AS total
FROM mytable;