Region-Area-Point of interest query optimization - tsql

My database has following structure:
Every Region (CountryStates) can have many cities (Areas). Every Area can have many tourist attractions or points of interest (POIs). I want to get list of how many Areas and Attractions are there in each Region. If there is none, I want to display 0.
This is my query:
SELECT Tab1.Reg AS Reg, CountAreas, CountPois
FROM
(SELECT
c.Name AS Reg,
COUNT(a.Id) AS CountAreas
FROM
CountryStates as c LEFT JOIN
Areas AS a ON a.CountryStates_Id = c.Id
GROUP BY c.Name
) as Tab1 left join
(SELECT
c1.Name AS Reg,
COUNT(p.Id) AS CountPois
FROM
CountryStates as c1 LEFT JOIN
Areas AS a ON a.CountryStates_Id = c1.Id LEFT JOIN
POIs AS p ON a.Id = p.Areas_Id
GROUP BY c1.Name
) as Tab2 on Tab1.Reg = Tab2.Reg
How can I make this query in just one SELECT?

This query returns the same result:
SELECT c.Name AS Reg,
COUNT(DISTINCT(a.Id)) AS CountAreas,
COUNT(p.Id) AS CountPois
FROM CountryStates as c
LEFT JOIN Areas as a ON a.CountryStates_Id = c.Id
LEFT JOIN POIs AS p ON a.Id = p.Areas_Id
GROUP BY c.Name

Related

Left [Outer] Join without Intersection to get count

I have the following schema
I wanted to get all cars along with number of models for each car and number of remaining colors for each car.
I was able to get number of models but i am not able to get number of remaining colors for each car. I know i have to do Left [Outer] Join without Intersection. But its not working
I may also have model which does not have any colors. In such case there wont be any entry in ModelColors table
select
c.CarID,
c.CarName,
T1.[Num Of Models],
T2.[Remaining Colors]
from Cars c
LEFT JOIN
(
SELECT m.CarID, COUNT(1) AS 'Num Of Models'
FROM Models m
GROUP BY m.CarID
) AS T1 ON T1.CarID = c.CarID
LEFT JOIN
(
SELECT m1.CarID, COUNT(1) AS 'Remaining Colors'
FROM Colors col
LEFT JOIN ModelColors mc on mc.ColorID = col.ColorID
LEFT JOIN Models m1 on m1.ModelID = mc.ModelID
WHERE mc.ColorID IS NULL
GROUP BY m1.CarID
) AS T2 ON T2.CarID = c.CarID
Your from/join clause in the second derived table (T2) is wrong.
You should use Models and ModelColors only:
SELECT m1.CarID, COUNT(1) AS 'Remaining Colors'
FROM Models m
LEFT JOIN ModelColors mc
ON m.ModelID = mc.ModelID
The entire query should look like this:
SELECT
c.CarID,
c.CarName,
T1.[Num Of Models],
T2.[Remaining Colors]
FROM Cars c
LEFT JOIN
(
SELECT m.CarID, COUNT(1) AS 'Num Of Models'
FROM Models m
GROUP BY m.CarID
) AS T1 ON T1.CarID = c.CarID
LEFT JOIN
(
SELECT m1.CarID, COUNT(1) AS 'Remaining Colors'
FROM Models m
LEFT JOIN ModelColors mc
ON m.ModelID = mc.ModelID
) AS T2 ON T2.CarID = c.CarID
Since you only want to count the colors, you don't need the Colors table at all for this query.

Problems with Postgresql ERROR: subquery uses ungrouped column "ev.title" from outer query

I have a query like this:
select c.id, c.name, c.website, c.longdescription, c.description, c.email,
(SELECT jsonb_agg(ev) FROM
(SELECT ev.title, ev.description, ev.longdescription,
(SELECT jsonb_agg(ed) FROM
(SELECT ed.startdate, ed.enddate, ed.id WHERE ed.id notnull)ed) as dates, ev.id WHERE ev.id notnull) ev) as events,
(SELECT jsonb_agg(ca) FROM (SELECT ct.zip, ca.id, ca.street1, ca.street2, ca.addresstype_id, ST_Y(ca.geopoint::geometry) as latitude, ST_X(ca.geopoint::geometry) as longitude
WHERE ca.id notnull)ca) as addresses
FROM companies c
LEFT JOIN events ev ON ev.company_id = c.id
LEFT JOIN companyaddresses ca ON ca.company_id = c.id
LEFT JOIN cities ct ON ct.id = ca.city_id
LEFT JOIN eventdates ed ON ed.event_id = ev.id
GROUP by c.id
I am getting the error "ERROR: subquery uses ungrouped column "ev.title" from
outer query Position: 125".
Can't figure out how to group it correctly for the subqueries. Any suggestions?
Give this a try:
SELECT c.id, c.name, c.website, c.longdescription, c.description, c.email,
    (SELECT jsonb_agg(ev) FROM
        (SELECT even.title, even.description, even.longdescription,
            (SELECT jsonb_agg(ed) FROM
                (SELECT eventdates.startdate, eventdates.enddate, eventdates.id FROM eventdates WHERE eventdates.event_id = even.id)ed) as dates,
        even.id FROM events even WHERE even.company_id = c.id) ev) as events,
jsonb_agg((SELECT ca FROM (SELECT ct.zip, ca.id, ca.street1, ca.street2, ca.addresstype_id, ST_Y(ca.geopoint::geometry) as latitude, ST_X(ca.geopoint::geometry) as longitude WHERE ca.id notnull)ca)) as addresses
FROM companies c
LEFT JOIN companyaddresses ca ON ca.company_id = c.id
LEFT JOIN cities ct ON ct.id = ca.city_id
Group by c.id

how to solve this complicated sql query

these are the five given tables
http://i58.tinypic.com/53wcxe.jpg
this is the recomanded result
http://i58.tinypic.com/2vsrts7.jpg
please help how can i write a query to have this result.
no idea how!!!!
SELECT K.* , COUNT (A.Au_ID) AS AnzahlAuftr
FROM Kunde K
LEFT JOIN Auftrag A ON K.Kd_ID = A.Au_Kd_ID
GROUP BY K.Kd_ID,K.Kd_Firma,K.Kd_Strasse,K.Kd_PLZ,K.Kd_Ort
ORDER BY K.Kd_PLZ DESC;
SELECT COUNT (F.F_ID) AS AnzahlFahrt
FROM Fahrten F
RIGHT JOIN Auftrag A ON A.Au_ID = F.F_Au_ID
SELECT SUM (T.Ts_Strecke) AS SumStrecke
FROM Teilstrecke T
LEFT JOIN Fahrten F ON F.F_ID = T.Ts_F_ID
how to join these 3 in one?
Grouping on Strasse etc. is not necessary and can be quite expensive. What about this approach:
SELECT K.*, ISNULL(Au.AnzahlAuftr,0) AS AnzahlAuftr, ISNULL(Au.AnzahlFahrt,0) AS AnzahlFahrt, ISNULL(Au.SumStrecke,0) AS SumStrecke
FROM Kunde K
LEFT OUTER JOIN
(SELECT A.Au_Kd_ID, COUNT(*) AS AnzahlAuftr, SUM(Fa.AnzahlFahrt1) AS AnzahlFahrt, SUM(Fa.SumStrecke2) AS SumStrecke
FROM Auftrag A LEFT OUTER JOIN
(SELECT F.F_Au_ID, COUNT(*) AS AnzahlFahrt1, SUM(Ts.SumStrecke1) AS SumStrecke2
FROM Fahrten F LEFT OUTER JOIN
(SELECT T.Ts_F_ID, SUM(T.Ts_Strecke) AS SumStrecke1
FROM Teilstrecke T
GROUP BY T.Ts_F_ID) AS Ts
ON Ts.Ts_F_ID = F.F_ID
GROUP BY F.F_Au_ID) AS Fa
ON Fa.F_Au_ID = A.Au_ID
GROUP BY A.Au_Kd_ID) AS Au
ON Au.Au_Kd_ID = K.Kd_ID

How to aggregate calculation in SQL Server?

I have a following script to get the total unit but it gives me an error
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
Do I need to calculate SUM(ta.Qty) outside the main table?
SELECT
ta.ProductName
, SUM(ta.Total)
, SUM(SUM(ta.Qty) * ta.Unit)
FROM
tableA tA
INNER JOIN
tableB tB on tA.ID = tb.TableAID
INNER JOIN
tableC tc on ta.ID = tc.TableAID
INNER JOIN
tableD td on td.ID = tb.TableBID
GROUP BY
ta.ProductName
Here is a query in the AdventureWorks database that produces the same error (but might make some sense):
SELECT v.Name AS Vendor, SUM(SUM(p.ListPrice*d.OrderQty)+h.Freight)
FROM Production.Product p
INNER JOIN Purchasing.PurchaseOrderDetail d ON p.ProductID = d.ProductID
INNER JOIN Purchasing.PurchaseOrderHeader h ON h.PurchaseOrderID = d.PurchaseOrderID
INNER JOIN Purchasing.Vendor v ON v.BusinessEntityID = h.VendorID
GROUP BY v.Name
And here are two ways that I could rewrite that query to avoid the error:
SELECT v.Name AS Vendor, SUM(x.TotalAmount+h.Freight)
FROM (
SELECT PurchaseOrderID, SUM(p.ListPrice*d.OrderQty) AS TotalAmount
FROM Production.Product p
INNER JOIN Purchasing.PurchaseOrderDetail d ON p.ProductID = d.ProductID
GROUP BY PurchaseOrderID
) x
INNER JOIN Purchasing.PurchaseOrderHeader h ON h.PurchaseOrderID = x.PurchaseOrderID
INNER JOIN Purchasing.Vendor v ON v.BusinessEntityID = h.VendorID
GROUP BY v.Name
SELECT v.Name AS Vendor, SUM(x.TotalAmount+h.Freight)
FROM Purchasing.PurchaseOrderHeader h
INNER JOIN Purchasing.Vendor v ON v.BusinessEntityID = h.VendorID
CROSS APPLY (
SELECT SUM(p.ListPrice*d.OrderQty) AS TotalAmount
FROM Production.Product p
INNER JOIN Purchasing.PurchaseOrderDetail d ON p.ProductID = d.ProductID
WHERE d.PurchaseOrderID=h.PurchaseOrderID
) x
GROUP BY v.Name
The first query uses derived tables and the second one uses CROSS APPLY.

Filter table that I do a LEFT JOIN with

Here's my query at the moment:
SELECT A.*
FROM A
LEFT JOIN B ON B.a_id = A.id
Now, suppose there is a table C which relates directly to B. What I'd like to do is to filter out the records of table B based on C - how do I do that? I've tried placing the filter in the WHERE section:
SELECT A.*
FROM A
LEFT JOIN B ON B.a_id = A.id
LEFT JOIN C ON B.c_id = C.id
WHERE C.id > 10
The problem is that the preceding queryalso filters out table A's results. How do I achieve the result that I want?
you need to put that filter in join :
SELECT *
FROM A
LEFT JOIN
(
SELECT B.*
FROM B
INNER JOIN C ON B.c_id = C.id AND C.id > 10
) AS B ON B.a_id = A.id
it will not filter out the A's results .