POSTGRESQL : Combining two query result with different columns but same number of rows - postgresql

Im currently trying to combine 2 queries results in one.
These 2 queries has the same number of rows and are group by the same field but has different column.
This works :
SELECT Distinct
MAX(d.libelle) AS libelle_dpt,
MAX(d.code_dpt) AS code_dep,
MAX(r.libelle) AS libelle_region,
MAX(pd.pop_dep) AS nb_habitants,MAX(ls.nb_canton) AS nb_canton
FROM election_2015.commune c
LEFT JOIN (
SELECT MAX(c.code_canton) AS code_canton,Count(distinct c.code_canton) AS nb_canton
FROM election_2015.commune co
JOIN election_2015.departement d
ON co.code_dpt = d.code_dpt
JOIN election_2015.canton c
ON c.code_canton = co.code_canton
GROUP BY d.code_dpt
ORDER BY d.code_dpt ASC
) ls
ON ls.code_canton = c.code_canton
JOIN election_2015.departement d
ON d.code_dpt = c.code_dpt
JOIN election_2015.region r
ON d.code_region = r.code_region
JOIN election.popgent_all pd
ON pd.dep = d.code_dpt
GROUP BY d.code_dpt
But I was wondering if there is an other way to do this, maybe like an union but with rows?
Something like this (not working cause queries hasn't the same number of columns) :
SELECT Distinct
MAX(d.libelle) AS libelle_dpt,
MAX(d.id) AS id_dep,MAX(d.code_dpt) AS code_dep,
MAX(r.libelle) AS libelle_region,
MAX(pd.pop_dep) AS nb_habitants
FROM election_2015.commune c
LEFT JOIN election_2015.departement d
ON d.code_dpt = c.code_dpt
LEFT JOIN election_2015.region r
ON d.code_region = r.code_region
LEFT JOIN election.popgent_all pd
ON pd.dep = d.code_dpt
GROUP BY d.code_dpt
UNION
SELECT Count(distinct c.code_canton) AS nb_canton FROM election_2015.commune co
JOIN election_2015.departement d
ON co.code_dpt = d.code_dpt
JOIN election_2015.canton c
ON c.code_canton = co.code_canton
GROUP BY d.code_dpt
ORDER BY election_2015.departement.code_dpt ASC
Thanks for any help.
Alexandre

Related

Postgresql Removing duplicates in a strings in the row

I have this code here
select ri.restaurant_id, string_agg(t.cuisine,',') as ncuisine
from restaurant_items ri
join restaurants r on r.id = ri.restaurant_id
left join food_taxonomy t on ri.name ilike concat('%',t.keywords,'%')
where ri.restaurant_id = 1
group by ri.restaurant_id
which gets me this results
restaurant_id ncuisine
1. Italian,Italian,Italian,Italian,Italian,American,Italian,Italian,Italian,Italian,Italian,Italian,American,Italian,Italian,Italian,Italian,Italian,Italian,American,Italian,Italian,Italian,Italian,American,Italian,Italian,Italian,Italian,American,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Greek,Italian,Italian,Greek,Italian,Italian,Italian,Italian,Italian,American,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,French,Italian,Italian,American,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,Italian,American,Italian,Italian,Italian,Italian,Italian,American,French,American,Italian,Italian,American,American,Italian
is there a function that would go with my code and remove the duplicate strings in "ncuisine" so it only shows Italian, American and French?
I believe i can put something near the string_agg function but not sure what functions i can use.
Distinct will make the difference:
select ri.restaurant_id, string_agg(distinct t.cuisine,',') as ncuisine
from restaurant_items ri
join restaurants r on r.id = ri.restaurant_id
left join food_taxonomy t on ri.name ilike concat('%',t.keywords,'%')
where ri.restaurant_id = 1
group by ri.restaurant_id;

Replace subquery with appropriate join

how can i remove subquery with a join?
SELECT distinct t."groupId" FROM "contacts" c
INNER JOIN
(
SELECT DISTINCT td.* FROM "groups" g
INNER JOIN
"territory" td
ON
td."groupId" = g.id
WHERE g."orgId" = 3
)
t
ON
ST_Intersects(t.points, c."geoPoint")
WHERE c.id = 33 and c."orgId" = 3
There is nothing wrong with a subquery, but you should get rid of the dreaded DISTINCT:
SELECT td."groupId"
FROM territory AS td
WHERE EXISTS (SELECT 1 FROM contacts AS c
WHERE ST_Intersects(td.points, c."geoPoint")
AND c.id = 33
AND c."orgId" = 3)
AND EXISTS (SELECT 1 FROM groups AS g
WHERE td."groupId" = g.id
AND g."orgId" = 3);
If you insist in having no subqueries, use
SELECT DISTINCT t."groupId"
FROM contacts c
INNER JOIN territory td
ON ST_Intersects(td.points, c."geoPoint")
INNER JOIN groups g
ON td."groupId" = g.id
WHERE g."orgId" = 3
AND c.id = 33
AND c."orgId" = 3;
If you need to make sure that the st_intersects function is only called for rows from territory that match the join with groups, you will have to use a subquery. There is no other way to force a join order.

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 .