Group by one column and return several columns on multiple conditions - T-SQL - sql

I have two tables which I can generate with SELECT statements (joining multiple tables) as follows:
Table 1:
ID
Site
type
time
1
Dallas
2
01-01-2021
2
Denver
1
02-01-2021
3
Chicago
1
03-01-2021
4
Chicago
2
29-11-2020
5
Denver
1
28-02-2020
6
Toronto
2
11-05-2019
Table 2:
ID
Site
collected
deposited
1
Denver
NULL
29-01-2021
2
Denver
01-04-2021
29-01-2021
3
Chicago
NULL
19-01-2020
4
Dallas
NULL
29-01-2019
5
Winnipeg
13-02-2021
17-01-2021
6
Toronto
14-02-2020
29-01-2020
I would like the result to be grouped by Site, having on each column the COUNT of type=1 , type=2, deposited and collected, all of the 4 columns between a selected time interval. Example: (interval between 01-06-2020 and 01-06-2021:
Site
type1
type2
deposited
collected
Dallas
0
1
0
0
Denver
1
0
2
1
Chicago
1
1
0
0
Toronto
0
0
0
0
Winnipeg
0
0
1
1

How about union all and aggregation?
select site,
sum(case when type = 1 then 1 else 0 end) as type_1,
sum(case when type = 2 then 1 else 0 end) as type_2,
sum(deposited) as deposited, sum(collected) as collected
from ((select site, type, 0 as deposited, 0 as collected
from table1
) union all
(select site, null,
(case when deposited is not null then 1 else 0 end),
(case when collected is not null then 1 else 0 end)
from table2
)
) t12
group by site;

Combine your tables 1 and 2 with a join on Site
Use COUNT(CASE WHEN type = 1 then 1 END) as type1 and a similar construct for type 2
Use COUNT(CASE WHEN somedate BETWEEN '2020-06-01' and '2021-06-01' then 1 END) as ... for your dates

Related

SQL merge 3 tables

I have an sql query involving 2 tables and try to add a third one.
These are the tables
FreeBookPos
FreeBooK_ID
ArticleNr
Amount
FreeBook
ID
BookNr
Date
FreeFields
FreeFieldType
Value
SQLPrimeKey
The first two are linked this way
select FreeBookPos.ArticleNr, Format(FreeBooking.Date, 'yyyy_MM') as dt,
SUM(CASE WHEN FreeBook.BookNr = 0 THEN FreeBookPos.Amount ELSE 0 END) as TotalEntryAmount,
SUM(CASE WHEN FreeBook.BookNr = 1 THEN FreeBookPos.Amount ELSE 0 END) as TotalLeftAmount
From FreeBookPos
INNER JOIN FreeBook on FreeBookPos.FreeBook_ID = FreeBook.ID
group by FORMAT ( FreeBook.Date, 'yyyy_MM'), FreeBookPos.ArticleNr
order by dt, ArticleNr
Now I need to add the table 3. This table is linked via SQLPrimeKey to FeeBook table ID. I then need to have only the fields where FreeFields.Value 2 or 4 and FreeFields.FreeFieldType = 54.
I tried various options with join but never get the result. Would I need to first join table 2 and 3 and then with 1 in a separate step?
Table 1: FreeBookPos
FreeBook_ID ArticleNr Amount
1 145 12
2 145 6
3 143 4
4 145 1
5 145 42
Table 2: FreeBook
ID BookNr Date
1 1 2012-05-19
2 -1 2012-05-21
3 1 2012-05-22
4 -1 2012-05-24
5 -1 2012-06-25
Table 3: FreeFields
SQLPrimareyKey FreeFieldType Value
1 54 1
2 52 2
3 54 4
4 54 2
5 54 2
Result should be:
ArticleNr Dt TotalEntryAmount TotalLeftAmount
143 2012-05 4 0
145 2012-05 0 -1
145 2012-06 0 -42
Try the below -
select FreeBookPos.ArticleNr, Format(FreeBooking.Date, 'yyyy_MM') as dt,
SUM(CASE WHEN FreeBook.BookNr = 0 THEN FreeBookPos.Amount ELSE 0 END) as TotalEntryAmount,
SUM(CASE WHEN FreeBook.BookNr = 1 THEN FreeBookPos.Amount ELSE 0 END) as TotalLeftAmount
From FreeBookPos
INNER JOIN FreeBook on FreeBookPos.FreeBook_ID = FreeBook.ID
inner join FreeFields on FreeBook.ID=SQLPrimareyKey
where value in (2,4) and FreeFieldType = 54
group by FORMAT ( FreeBook.Date, 'yyyy_MM'), FreeBookPos.ArticleNr
order by dt, ArticleNr

Display output is columns based on filter criteria

I am trying to display data is columns/subcolumns based on certain filter criteria using case when statement but not getting required output.
data:
ID ID2 Country Type
1 001 US A
1 009 US A
2 002 AU B
3 003 CA A
3 005 CA A
4 007 US B
5 001 FR B
6 003 US B
7 002 US A
8 004 NZ A
based on my current case statement, here is how my output looks:
Type Country Count
B Other 2
B US 1
B Subtotal 3
A Other 4
A US 3
A Subtotal 7
Total 10
I want to display the following format, bonus if I can get the subtotal/totals:
Type-A Type-B
US Other US Other
3 4 1 2
I also need Subtotals, and Grandtotals, but these need to be calculated separately.
SubTotal: 7 SubTotal: 3
Grand Total: 10
You can like this
select
sum(case when Type = 'A' and Country = 'US' then 1 else 0 end) as US_TYPE_A,
sum(case when Type = 'A' and Country != 'US' then 1 else 0 end) as Other_TYPE_A,
sum(case when Type = 'B' and Country = 'US' then 1 else 0 end) as US_TYPE_B,
sum(case when Type = 'B' and Country != 'US' then 1 else 0 end) as Other_TYPE_B
from myTable

Multiple times Grouping with where in SQL Server

I have a source table like this
ProductName SaleReceipt SaleCode
--------------------------------
F-Apple 1001 1
F-Orange 1002 2
G-Rice 1003 3
G-Barile 1005 4
G-Oats 1006 1
V-Carrot 1007 4
V-Cabbage 1008 3
V-Potato 1009 1
V-Tomato 1010 1
Chocolate 1011 4
Cookies 1012 1
Cakes 1013 2
I need to create a report like this
30 Day delay 60 Day Delay 90 day delay 120 day delay
Fruits 1 1 0 0
Grains 1 0 1 1
Vegetables 2 0 1 1
Other category 1 1 0 1
The conditions to create the report are:
All ProductName start with F is grouped as fruits
All ProductName start with G is grouped as Grains
All ProductName start with V is grouped as Vegetables
Other product name go in the other category
30 day delay: count of (SaleReceipt) with a SaleCode=1
60 day delay: count of (SaleReceipt) with a SaleCode=2
90 day delay: count of (SaleReceipt) with a SaleCode=3
120 day delay: count of (SaleReceipt) with a SaleCode>=4
I could not find how to do grouping two times. I am using SQL Server 2014.
You can use case in a group by. Or use a lookup table:
select coalesce(c.name, 'Other category'),
sum(case when salescode = 1 then 1 else 0 end) as salecode_1,
sum(case when salescode = 2 then 1 else 0 end) as salecode_2,
sum(case when salescode = 3 then 1 else 0 end) as salecode_3,
sum(case when salescode = 4 then 1 else 0 end) as salecode_4
from t left join
(values ('F-%', 'Fruit'), ('G-%' , 'Grain'), ('V-%', 'Vegetable')
) c(pattern, name)
on t.productname like c.pattern
group by coalesce(c.name, 'Other category');

SQL Query. limit an update per rows if condition is X and Y for the same ID number

Have the following table tblTrans where
Trans_ID Trans Sequence Trans_PointsEarned Trans_PointsApplied
4452 1 1 1
4452 2 1 1
4452 3 0 1
4462 1 1 1
4462 2 1 1
4462 3 1 1
4462 4 1 1
4462 5 1 1
9101 1 0 1
9101 2 0 1
9101 3 0 1
9101 4 0 1
(useless table doesnt work)
I need to set the following on another field per every customer ID.
So Customer_OverallPoints
4452 = 2 (doesn't count 0's)
4462 = 4 (I want to cap the points to 4 based on the sequence and transID and customerID)
9101 = 0 (dont count 0's).
This needs to be applied to thousands of records based on customerID and TransID where Trans_Sequence is within the same Trans_ID and it only counts the first 4 rows that have the Trans_pointsEarned = 1.
I tried putting a psuedocode together but it just looked ridicilous and I can't even come up with the logic for this.
Thanks
Assuming that TransId is really the customer id, I think the basic logic is just an aggregation:
select t.TransId,
(case when sum(t.Trans_PointsEarned) > 4 then 4
else sum(t.Trans_PointsEarned)
end) as Customer_OverallPoints
from tblTrans t
group by t.TransId;
You can put this into an update statement as:
update customers c
set Customer_OverallPoints = (select (case when sum(t.Trans_PointsEarned) > 4 then 4
else sum(t.Trans_PointsEarned)
end)
from tblTrans t
where t.TransId = c.CustomerId
);

Need a SQL query to get data based on condition based on count

I have tables called areadetail and state.
areadetail has these columns:
State Id
Area Id-rural(1) or urban(2)
Population
Sample data:
Stateid AreaID Population
1 1 10
1 2 20
1 2 20
2 1 10
2 2 20
3 1 10
State table has these columns:
State name and state id
Sample data:
State Id StateName
1 Delhi
2 Mumbai
3 Jaipur
Now I need a query to display records like
State name Rural Urban
------------------------------------------
Delhi 3 2
Mumbai 1 1
Jaipur 1 0
I guess AreaID=1 means RURAL and 2 is URBAN then try this query:
SELECT
MAX(s.StateName),
SUM(CASE WHEN ad.AreaID=1 THEN ad.Population ELSE 0 END) as Rural ,
SUM(CASE WHEN ad.AreaID=2 THEN ad.Population ELSE 0 END) as Urban
FROM State as s
LEFT JOIN areadetail as ad on s.Stateid=ad.Stateid
GROUP BY s.Stateid
SQLFiddle demo
Select name,Rural,Urban
from
(
Select state, sum(case when area= 1 then 1 else 0 end) 'Rural',sum(case when area= 2 then 1
else 0 end) 'Urban'
from #Area
group by state
) A
join State S
on A.state = S.state