Get Total Branch wise in SQL Server - sql

SELECT b.BranchName ,
pm.AgreementValue
FROM dbo.Member AS m
INNER JOIN dbo.PlanMaster AS pm ON ( m.PlanId = pm.PlanId )
INNER JOIN dbo.Branch AS b ON ( b.BranchId = m.BranchId )
this is the result of above query
BranchName AgreementValue
------------------------------
abc 60000.00
abc 36000.00
abc 36000.00
xyz 20000.00
xyz 10000.00
now i want to get to total of AgreementValue BranchName wise..thanks for help

GROUP BY b.BranchName with SUM like so:
SELECT b.BranchName ,
SUM(pm.AgreementValue) TotalValue
FROM dbo.Member AS m
INNER JOIN dbo.PlanMaster AS pm ON ( m.PlanId = pm.PlanId )
INNER JOIN dbo.Branch AS b ON ( b.BranchId = m.BranchId )
GROUP BY b.BranchName;

If you are trying to get the total on each row, then use the window function for sum():
SELECT b.BranchName ,
pm.AgreementValue,
sum(pm.AgreementValue) over (partition by b.BranchName) as BranchTotal
FROM dbo.Member AS m
INNER JOIN dbo.PlanMaster AS pm ON ( m.PlanId = pm.PlanId )
INNER JOIN dbo.Branch AS b ON ( b.BranchId = m.BranchId )

Related

Is there a way to join two queries in SQL each with an order by?

I have two queries that return data from two tables:
SELECT TOP 3
AE.id, AE.name, COUNT(R.id) 'number of reserves'
FROM
AIRPORT AE
INNER JOIN
FLY V ON V.id_destiny = AE.id
INNER JOIN
RESERVE R ON R.id_fly = V.id
GROUP BY
AE.id, AE.name
ORDER BY
COUNT(R.id) DESC;
Example of returned data:
id
name
number of reserves
6
name1
27
4
name2
18
14
name3
14
and
SELECT TOP 3
AE.id, AE.name, COUNT(R.id) 'number of reserves'
FROM
AEROPUERTO AE
LEFT JOIN
FLY V ON V.id_destiny = AE.id
LEFT JOIN
RESERVE R ON R.id_fly = V.id
GROUP BY
AE.id, AE.name
ORDER BY
COUNT(R.id) ASC;
Example of data returned from this second query:
id
name
number of reserves
7
name4
0
11
name5
0
12
name6
0
I need to combine these into a single output with the first query first (in the same order) and the second query next with the same order like this:
id
name
number of reserves
6
name1
27
4
name2
18
14
name3
14
7
name4
0
11
name5
0
12
name6
0
Is there a way to do it?
Edit: I have already tried the union all option, but I can't use the group by in each query so the table that is returned is different from what I need
(SELECT TOP 3 AE.id, AE.name, COUNT(R.id) 'number of reserves'
FROM AIRPORT AE
INNER JOIN FLY V
ON V.id_destiny = AE.id
INNER JOIN RESERVE R
ON R.id_fly = V.id
GROUP BY AE.id, AE.name)
UNION ALL
(SELECT TOP 3 AE.id, AE.name, COUNT(R.id) 'number of reserves'
FROM AEROPUERTO AE
LEFT JOIN FLY V
ON V.id_destiny= AE.id
LEFT JOIN RESERVE R
ON R.id_fly = V.id
GROUP BY AE.id, AE.name)
ORDER BY COUNT(R.id) ASC;
When you enclosed each query in parenthesis, it is acting like a derived table. You will need a SELECT clause to select from the derived table.
SELECT *
FROM
(
-- Your first query here
) AS Q1
UNION ALL
SELECT *
FROM
(
-- Your second query here
) AS Q2
You may also use CTE to do it
WITH
Q1 AS
(
-- Your first query here
),
Q2 AS
(
-- Your second query here
)
SELECT *
FROM Q1
UNION ALL
SELECT *
FROm Q2
EDIT : if you also wanted the final result in the same order in both query, add another column for final query ORDER BY
WITH
Q1 AS
(
SELECT TOP 3
AE.id, AE.name, COUNT(R.id) 'number of reserves',
Q = 1,
RN = ROW_NUMBER() OVER (ORDER BY COUNT(R.id) DESC)
FROM
AIRPORT AE
INNER JOIN
FLY V ON V.id_destiny = AE.id
INNER JOIN
RESERVE R ON R.id_fly = V.id
GROUP BY
AE.id, AE.name
ORDER BY
COUNT(R.id) DESC
),
Q2 AS
(
SELECT TOP 3
AE.id, AE.name, COUNT(R.id) 'number of reserves',
Q = 2,
RN = ROW_NUMBER() OVER (ORDER BY COUNT(R.id) DESC)
FROM
AEROPUERTO AE
LEFT JOIN
FLY V ON V.id_destiny = AE.id
LEFT JOIN
RESERVE R ON R.id_fly = V.id
GROUP BY
AE.id, AE.name
ORDER BY
COUNT(R.id) ASC
)
SELECT *
FROM Q1
UNION ALL
SELECT *
FROM Q2
ORDER BY Q, RN
I break the query and made two temp tables. You can do this in CTE (Commn Table expression) as well.
SELECT TOP 3 AE.id, AE.name, COUNT(R.id) 'number of reserves'
INTO #Temp_1
FROM AIRPORT AE
INNER JOIN FLY V
ON V.id_destiny = AE.id
INNER JOIN RESERVE R
ON R.id_fly = V.id
GROUP BY AE.id, AE.name
SELECT TOP 3 AE.id, AE.name, COUNT(R.id) 'number of reserves'
into #Temp_2
FROM AEROPUERTO AE
LEFT JOIN FLY V
ON V.id_destiny= AE.id
LEFT JOIN RESERVE R
ON R.id_fly = V.id
GROUP BY AE.id, AE.nam
SELECT *
FROM #Temp_1
UNION ALL
SELECT *
FROM #Temp_2
drop table #Temp_1
drop table #Temp_2

FULL OUTER JOIN of two INNER JOINs

I have three tables.
My Table Order has an Id and a Date.
Likewise my table Delivery has an Id and a Date.
My third table Part has an Id, and two foreign keys to Order and Delivery: OrderId, DeliveryId.
I want to create a query that gives me an overview over the count of orders and deliveries per month, like this:
+------+-------+------------+---------------+
| Year | Month | OrderCount | DeliveryCount |
+------+-------+------------+---------------+
| 2021 | 2 | 10 | 12 |
+------+-------+------------+---------------+
| 2021 | 1 | 234 | 213 |
+------+-------+------------+---------------+
| ... | ... | ... | ... |
+------+-------+------------+---------------+
So I created a query that gives me the orders per month:
SELECT
MONTH(o.[Date]) AS [Month],
YEAR(o.[Date]) AS [YEAR],
COUNT(p.Id) AS OrderCount
FROM
Part AS p
INNER JOIN
[Order] AS o ON o.Id = p.OrderId
GROUP BY
MONTH(o.[Date]), YEAR(o.[Date])
and one for the deliveries per month:
SELECT
MONTH(d.[Date]) AS [Month],
YEAR(d.[Date]) AS [YEAR],
COUNT(p.Id) AS DeliveryCount
FROM
Part AS p
INNER JOIN
Delivery AS d ON d.Id = p.DeliveryId
GROUP BY
MONTH(d.[Date]), YEAR(d.[Date])
But now I am struggling with joining them. I think I need a FULL OUTER JOIN, because I need the Month/Year/DeliveryCount when there is no order but deliveries and vice versa.
What I have tried is
SELECT
MONTH(o.Date) AS [Month]
YEAR(o.Date) as [Year]
COUNT(p.Id) as OrderCount
FROM
Part AS p
INNER JOIN
[Order] AS o ON o.Id = p.OrderId
GROUP BY
MONTH(o.Date), Year(o.Date)
FULL OUTER JOIN
(SELECT
MONTH(d.Date) AS [Month]
YEAR(d.Date) as [Year]
COUNT(pp.Id) as DeliveryCount
FROM
Part AS pp
INNER JOIN
Delivery AS d ON d.Id = pp.DeliveryId
GROUP BY
MONTH(d.Date), YEAR(d.Date)) AS d ON d.[Month] = MONTH(o.Date) AND d.[Year] = YEAR(o.Date)
But that's not how FULL OUTER JOINS work.
How do I get a full outer of these two inner joins?
Or is this approach of outer joining two inner joins wrong in the first place?
You have to treat your two queries as sub-queries.
This should give you the desired result
Select Orders.OrderCount, Deliveries.DeliveryCount
from (
SELECT
MONTH(o.Date) AS [Month]
YEAR(o.Date) AS [YEAR]
COUNT(p.Id) AS OrderCount
FROM
Part AS p
INNER JOIN
[Order] AS o ON o.Id = p.OrderId
GROUP BY
MONTH(o.Date), YEAR(o.Date)
) Orders
FULL OUTER JOIN
(
SELECT
MONTH(d.Date) AS [Month]
YEAR(d.Date) AS [YEAR]
COUNT(p.Id) AS DeliveryCount
FROM
Part AS p
INNER JOIN
Delivery AS d ON d.Id = p.DeliveryId
GROUP BY
MONTH(d.Date), YEAR(d.Date) ) Deliveries
on Orders.Month = Deliveries.Month
and Orders.Year = Deliveries.Year
This would solve your problem.
In case you have months/year missing, use other join.
WITH OrdersMonth AS (
SELECT
MONTH(o.Date) AS [Month]
YEAR(o.Date) AS [YEAR]
COUNT(p.Id) AS OrderCount
FROM
Part AS p
INNER JOIN
[Order] AS o ON o.Id = p.OrderId
GROUP BY
MONTH(o.Date), YEAR(o.Date)
), DeliveriesMonth AS (
SELECT
MONTH(d.Date) AS [Month]
YEAR(d.Date) AS [YEAR]
COUNT(p.Id) AS DeliveryCount
FROM
Part AS p
INNER JOIN
Delivery AS d ON d.Id = p.DeliveryId
GROUP BY
MONTH(d.Date), YEAR(d.Date)
)
SELECT om.YEAR
,om.Month
,om.OrderCount
,dm.DeliveryCount
FROM OrdersMonth om
LEFT JOIN DeliveriesMonth dm ON om.om.YEAR = dm.YEAR AND om.Month = dm.Month

How to use PIVOT in SQL for this sample

How do I pivot a results query?
Currently it looks like this
| Date | Count | BankName |
+---------+----------+----------+
| 970401 | 87 | Saderat |
| 970401 | 25 | Melli |
| 970401 | 11 | Sina |
into this
|Date | Saderat | Melli | Sina |
+---------+----------+----------+----------+
|970401 | 87 | 25 | 11 |
I tried the following but it's not working
SELECT
PayDate AS [Date],
COUNT(*) AS [Count], b.BankName
FROM
Payments p
INNER JOIN
dbo.Accounts a ON a.AccountId = p.CashAccountId
INNER JOIN
dbo.Banks b ON b.BankId = a.BankId
WHERE
PayTypeId = 21.101
AND PayDate BETWEEN '970401' AND '970412'
GROUP BY
PayDate, b.BankName
ORDER BY
paydate
or
SELECT
x.PayDate AS 'Date',
b.BankName
FROM
(SELECT
p.PayDate, p.PaymentId, p.CashAccountId
FROM
Payments p
WHERE
PayTypeId = 21.101
AND PayDate BETWEEN '970401' AND '970412') AS x
INNER JOIN
dbo.Accounts a ON a.AccountId = x.CashAccountId
INNER JOIN
dbo.Banks b ON b.BankId = a.BankId
PIVOT
(COUNT(PaymentId) FOR PayDate IN (bankid)) AS Pivotable
You can try following SQL for required results:
SELECT PayDate, Saderat, Melli, Sina
FROM
(SELECT PayDate , COUNT(*) AS [Count] , b.BankName
FROM Payments p INNER JOIN dbo.Accounts a ON a.AccountId = p.CashAccountId
INNER JOIN dbo.Banks b ON b.BankId = a.BankId
WHERE PayTypeId = 21.101 AND PayDate BETWEEN '970401' AND '970412'
GROUP BY PayDate , b.BankName
ORDER BY paydate) AS SourceTable
PIVOT
(
SUM([Count])
FOR BankName IN (Saderat, Melli, Sina)
) AS PivotTable;
You can do aggregation :
SELECT PayDate AS [Date],
SUM(CASE WHEN b.BankName = 'Saderat' THEN 1 ELSE 0 END) AS Saderat,
. . .
FROM Payments p INNER JOIN
dbo.Accounts a
ON a.AccountId = p.CashAccountId INNER JOIN
dbo.Banks b
ON b.BankId = a.BankId
WHERE PayTypeId = 21.101 AND PayDate BETWEEN '970401' AND '970412'
GROUP BY PayDate
ORDER BY paydate;
You can use PIVOT function in SQL Server, try following query:
SELECT date, [Saderat],[Melli],[Sina]
FROM YourTableName
PIVOT( MAX(count)
FOR BankName IN ([Saderat],[Melli],[Sina])) AS p
You could PIVOT
SELECT *
FROM
(
SELECT
p.PayDate AS [Date],
b.BankName
FROM dbo.Payments p
JOIN dbo.Accounts a ON a.AccountId = p.CashAccountId
JOIN dbo.Banks b ON b.BankId = a.BankId
WHERE p.PayTypeId = 21.101
AND p.PayDate BETWEEN CAST('1997-04-01' AS DATE) AND CAST('1997-04-12' AS DATE)
) src
PIVOT
(
COUNT(*)
FOR BankName IN (...) -- put quoted list of bank names here
) pvt
ORDER BY [Date]

Count Customers based on item master

I need you to help me on writing two queries in SQL Server 2008 that shows the following information based on item master:
Brand wise count on customer master plus customer who purchased the brand
Item Wise count of customer master plus customer who purchased the item
Here the link that shows the table information and the query which I tried.
Click here to view the table in SQL Fiddle
SELECT
brandname,
division,
route,
DivisionTotalCustomersCount = MAX(DivisionTotalCustomersCount),
RouteTotalCustomersCount = MAX(RouteTotalCustomersCount),
PurchasedCustomersCount = SUM(PurchasedCustomersCount)
FROM
(SELECT
i.brandname,
c.division,
c.route,
DivisionTotalCustomersCount =
(SELECT COUNT(distinct x.CustomerID)
FROM CustomerMaster x
WHERE x.division = c.division),
RouteTotalCustomersCount =
(SELECT COUNT(distinct x.CustomerID)
FROM CustomerMaster x
WHERE x.Route = c.route),
PurchasedCustomersCount = count(distinct C.CustomerID)
FROM CustomerMaster c
LEFT OUTER JOIN SalesData s on c.CustomerID = s.CustomerID
right outer join ItemMaster i on s.item = i.itemcode
GROUP BY i.brandname, c.division, c.route) A
GROUP BY
brandname, division, route
ORDER BY 1
Result Should as below
Excelsheet
I think you need to go reconsider the report and maybe splitting it out into multiple reports.
It does not make sense to have a route count as well as a divisional count if they are counting things at different levels of aggregation. So have a route count and division count report.
Either way, division and route is going to be null for 100PLUS because there are no customers for that brand which means there is no route or division info available.
--Division Count
SELECT BrandName, Division, COUNT(CustomerMaster.CustomerID) [Customer Count]
FROM ItemMaster LEFT OUTER JOIN
SalesData ON ItemMaster.BrandName = SalesData.Brand LEFT OUTER JOIN
CustomerMaster ON SalesData.CustomerID = CustomerMaster.CustomerID
GROUP BY BrandName, Division
--Route Count
SELECT BrandName, Route, Division, COUNT(CustomerMaster.CustomerID) [Customer Count]
FROM ItemMaster LEFT OUTER JOIN
SalesData ON ItemMaster.BrandName = SalesData.Brand LEFT OUTER JOIN
CustomerMaster ON SalesData.CustomerID = CustomerMaster.CustomerID
GROUP BY BrandName, Route, Division
Using your sqlfiddle data there are 25 sales records & 18 distinct brand/ division/ route/ customer records and there are no sales invloving 100PLUS
select
B.BrandName
, V.Division
, coalesce(Brand_count,0) as Brand_count
, coalesce(Division_count,0) as Division_count
from (select distinct BrandName from ItemMaster) as B
cross join (select distinct Division from CustomerMaster) as V
left join (
select
Brand
, Division
, sum(cust_count) over (partition by Brand) as Brand_count
, sum(cust_count) over (partition by Division) as Division_count
from (
select
S.Brand
, C.Division
, count(distinct S.CustomerID) cust_count
from salesdata as S
inner join CustomerMaster as C
on S.CustomerID = C.CustomerID
inner join ItemMaster as I
on S.item = I.ItemCode
group by
S.Brand
, C.Division
) as S
) as D
on B.BrandName = D.Brand
and V.Division = D.Division
order by
B.BrandName
, V.Division
;
| BRANDNAME | DIVISION | BRAND_COUNT | DIVISION_COUNT |
|-----------|----------|-------------|----------------|
| 100PLUS | Dubai | 0 | 0 |
| 100PLUS | RAK | 0 | 0 |
| KITCO | Dubai | 9 | 11 |
| KITCO | RAK | 9 | 7 |
| Red Bull | Dubai | 9 | 11 |
| Red Bull | RAK | 9 | 7 |
http://sqlfiddle.com/#!3/fecb0/27
All Credit to #kevriley
select
A.BrandName,
B.Division,
B.Route,
B.DivisionTotalCustomers,
B.RouteTotalCustomers,
isnull(C.PurchasedCustomersCount,0) as PurchasedCustomersCount
from
(
select distinct
BrandName, Route, Division
from dbo.ItemMaster
cross join dbo.CustomerMaster
) A
join
(
select distinct
Division,
Route,
DENSE_RANK() over (partition by Division order by c.CustomerID asc) + DENSE_RANK() over (partition by Division order by c.CustomerID desc) - 1 as DivisionTotalCustomers ,
DENSE_RANK() over (partition by ROUTE order by c.CustomerID asc) + DENSE_RANK() over (partition by ROUTE order by c.CustomerID desc) - 1 as RouteTotalCustomers
from CustomerMaster c
left join SalesData s on c.CustomerID = s.CustomerID
) B on B.Division = A.Division and B.Route = A.Route
left join
(
select
s.brand,
c.division,
c.route,
PurchasedCustomersCount = count(distinct C.CustomerID)
FROM CustomerMaster c
JOIN SalesData s on c.CustomerID = s.CustomerID
--join ItemMaster i on s.item = i.itemcode
GROUP by s.brand, c.division, c.route
) C on A.Brandname = C.Brand and C.Division = A.Division and C.Route = A.Route
See the same on SQL Fiddle
Select B.Brandname,B.Division,C AS DivisionTotalCustomerCount,
ISNULL(T.Count,0) AS PURCHASEDCUSTOMERSCOUNT
from
(
Select CM.Division,M.BrandName,COUNT(distinct CM.CustomerID) AS C
from dbo.CustomerMaster CM
CROSS JOIN ItemMaster M
GROUP BY CM.Division,M.BrandName
)B
LEFT JOIN
(Select Division,Brand,COUNT(Distinct C.CustomerID) As Count from CustomerMaster C
JOIN salesdata D
On C.CustomerID=D.CustomerID
where D.Brand='Red Bull'
GROUP BY Division,Brand
)T
ON B.Brandname=T.Brand
and B.Division=T.Division
Order by 1,2

I want to write a query to print sum of data for all TC into single table

I have this query to select distinct TCName values from a table:
SELECT DISTINCT(TCName)
FROM [dbo].[TCDetails]
This is another query to sum a data into table:
SELECT
sum(BS.BLDOS) as BLDOS,
sum(BS.CollectedAmount) as CollectedAmount
FROM [Customer] C
INNER JOIN [dbo].[BillingStatus] BS
ON BS.CustomerID = C.CustomerID
INNER JOIN [dbo].[TCDetails] TC
ON TC.CustomerID = BS.CustomerID
I want to write a query so that I am able to print sum of data for all TC into single table
I try this but It's not working
SELECT
sum(BS.BLDOS) as BLDOS,
sum(BS.CollectedAmount) as CollectedAmount
FROM [Customer] C
INNER JOIN [dbo].[BillingStatus] BS
ON BS.CustomerID = C.CustomerID
INNER JOIN [dbo].[TCDetails] TC
ON TC.CustomerID = BS.CustomerID
WHERE TCName in
(
Select distinct
(TCName)
FROM [dbo].[TCDetails]
)
I wanted to print it like
TCName | sum(BS.BLDOS) | sum(BS.CollectedAmount)
xyz | 23456 | 6755
tyu | 34556 | 567898
bnv | 21467 | 345
You need a group by if you want multiple rows in the output
SELECT TCName, sum(BS.BLDOS) as BLDOS, sum(BS.CollectedAmount) as CollectedAmount
FROM [Customer] C INNER JOIN
[dbo].[BillingStatus] BS
ON BS.CustomerID = C.CustomerID INNER JOIN
[dbo].[TCDetails] TC
ON TC.CustomerID = BS.CustomerID
WHERE TCName in (Select distinct(TCName) FROM [dbo].[TCDetails])
GROUP BY TCName;