Postgresql: UNION ALL on two queries using "with <name> as"? - postgresql

I have this query:
with active_cars as (
select c.id
from car c
inner join dealership d on c.dealer_id = d.id and d.active=true and d.ownerId=${userId}
)
select cd.*
from car_details cd
inner join active_cars ac on cd.car_id = ac.id
where cd.ratings=5;
Then I have query:
with ports_active_cars as (
select c.id
from car c
inner join ports p on c.port_id = p.id and p.active=true and p.ownerId=${userId}
)
select cd.*
from car_details cd
inner join ports_active_cars pac on cd.car_id = pac.id
I'd like to know how I can combine the result of the two queries into one, so I get one result including all car_details records.
I tried this:
with active_cars as (
select c.id
from car c
inner join dealership d on c.dealer_id = d.id and d.active=true and d.ownerId=${userId}
)
select cd.*
from car_details cd
inner join active_cars ac on cd.car_id = ac.id
where cd.ratings=5
union all
with ports_active_cars as (
select c.id
from car c
inner join ports p on c.port_id = p.id and p.active=true and p.ownerId=${userId}
)
select cd.*
from car_details cd
inner join ports_active_cars pac on cd.car_id = pac.id;
but that is wrong, does not run.
Is there a way to combine the two into one result returning all rows of car_details?

You need to define both CTEs at the start of the statement:
with active_cars as (
select c.id
from car c
inner join dealership d
on c.dealer_id = d.id and d.active = true and d.ownerId = ${userId}
),
ports_active_cars as (
select c.id
from car c
inner join ports p
on c.port_id = p.id and p.active=true and p.ownerId = ${userId}
)
select cd.*
from car_details cd
inner join active_cars ac on cd.car_id = ac.id
where cd.ratings = 5
union all
select cd.*
from car_details cd
inner join ports_active_cars pac on cd.car_id = pac.id;

Related

Jasper Report: error executing SQL statement by Collection Parameter

I'm creating a report which's passing by collection parameter.
The parameter name as 'ids' and the class is java.util.Collection.
My query:
select * from order_deliveryorder a
left join order_deliveryorderline b on a.id = b.d_order_id
left join order_item c on c.id = b.product_id
left join order_orderline e on e.id = b.s_order_id
left join order_order f on e.order_id = f.id
left join order_itemsection g on g.id = f.section_id
left join order_location d on d.id = a.location_id
left join order_location h on h.id = a.from_location_id
where a.id in ('2377900603251741014','2377900603251740997','2377900603251740967')
the query in jasper:
select * from order_deliveryorder a
left join order_deliveryorderline b on a.id = b.d_order_id
left join order_item c on c.id = b.product_id
left join order_orderline e on e.id = b.s_order_id
left join order_order f on e.order_id = f.id
left join order_itemsection g on g.id = f.section_id
left join order_location d on d.id = a.location_id
left join order_location h on h.id = a.from_location_id
where $X{IN, a.id, ids}
The value of parameter "ids" is ["2377900603251741014","2377900603251740997","2377900603251740967"]
In the End, had met the error executing sql statement.

Filter using NOT IN with more than one column

Is there a better way to write the following query to minimize code repetition in the WHERE statement?
SELECT TA.*
FROM TA
JOIN TB on TA.id = TB.id
JOIN TC on TB.id =TC.id
JOIN TD on TC.id = TD.id
JOIN TE on TD.id = TE.id
WHERE TC.Name NOT IN (‘John’,’William’,’Jacob’,’Henry’,’David’)
AND TD.Name NOT IN (‘John’,’William’,’Jacob’,’Henry’,’David’)
AND TE.Name NOT IN (‘John’,’William’,’Jacob’,’Henry’,’David’)
Note: The filter is always the same: NOT IN (‘John’,’William’,’Jacob’,’Henry’,’David’)
Using exists with a table value constructor you can do something like this:
SELECT TA.*
FROM TA
JOIN TB on TA.id = TB.id
JOIN TC on TB.id =TC.id
JOIN TD on TC.id = TD.id
JOIN TE on TD.id = TE.id
WHERE NOT EXISTS (
SELECT 1
FROM (VALUES('John'),('William'),('Jacob'),('Henry'),('David')) V(name)
WHERE Name IN(TC.Name, TD.Name, TE.Name)
)

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.

Row_Number () Over Certain Value Rows

SELECT
ROW_NUMBER() OVER (PARTITION BY s.ExitStateTypeId ORDER BY s.InsertDate) AS Number
,x.Id
,p.FirstName
,p.LastName
,p.PN
,t.Name
,s.ExitStateTypeId as [Status]
,g.Name
,x.OrganisationId
,d.Name AS Direction
,d.Id AS DirectionId
,h.Name AS Referal
,h.Id AS HealthOrgTypeId
,s.IssueDate
,s.InsertDate
FROM [DB1].[dbo].[Exits] x
INNER JOIN [DB1].[dbo].[ExitStates] s on x.Id = s.ExitId
INNER JOIN [DB1].[dbo].[HealthOrgTypes] h on x.HealthOrgTypeId = h.Id
INNER JOIN [DB1].[dbo].[Directions] d on x.DirectionId = d.Id
INNER JOIN [DB1].[dbo].[HealthCards] c on x.HealthCardId = c.Id
INNER JOIN [DB2].[pr].[TABLE] p on p.Id = c.TABLEId
INNER JOIN [DB3].[orgs].[Organizations] g on g.Id = x.OrganisationId
INNER JOIN [DB4].[dbo].ExitStateTypes t on t.Id = s.ExitStateTypeId
WHERE s.Id = (SELECT MAX(es.Id) from ExitStates es WHERE es.ExitId=x.Id)
ORDER BY s.InsertDate
This is my query, but what I need is that I want only those rows to be enumerated by ROW_NUMBER which s.ExitStateTypeId is in (4,7), for the other rows it should be -1.
Here's the incorrect query just for getting the idea.
SELECT
ROW_NUMBER() OVER (PARTITION BY s.ExitStateTypeId Where s.ExitStateTypeId IN (4,7)
ORDER BY s.InsertDate) AS Number
,x.Id
,p.FirstName
,p.LastName
,p.PN
,t.Name
,s.ExitStateTypeId as [Status]
,g.Name
,x.OrganisationId
,d.Name AS Direction
,d.Id AS DirectionId
,h.Name AS Referal
,h.Id AS HealthOrgTypeId
,s.IssueDate
,s.InsertDate
FROM [DB1].[dbo].[Exits] x
INNER JOIN [DB1].[dbo].[ExitStates] s on x.Id = s.ExitId
INNER JOIN [DB1].[dbo].[HealthOrgTypes] h on x.HealthOrgTypeId = h.Id
INNER JOIN [DB1].[dbo].[Directions] d on x.DirectionId = d.Id
INNER JOIN [DB1].[dbo].[HealthCards] c on x.HealthCardId = c.Id
INNER JOIN [DB2].[pr].[TABLE] p on p.Id = c.TABLEId
INNER JOIN [DB3].[orgs].[Organizations] g on g.Id = x.OrganisationId
INNER JOIN [DB4].[dbo].ExitStateTypes t on t.Id = s.ExitStateTypeId
WHERE s.Id = (SELECT MAX(es.Id) from ExitStates es WHERE es.ExitId=x.Id)
ORDER BY s.InsertDate
So, I want partition by s.ExitStateTypeId just when it is 4 or 7 and -1 for the others
This is data I expect
Perhaps with a combination of CASE and ROW_NUMBER:
SELECT Number = CASE WHEN s.ExitStateTypeId NOT IN (4,7) THEN -1
ELSE Row_number() OVER (
partition BY s.exitstatetypeid
ORDER BY s.insertdate) END,
x.id,
p.firstname,
p.lastname,
p.pn,
t.name,
s.exitstatetypeid AS [Status],
g.name,
x.organisationid,
d.name AS Direction,
d.id AS DirectionId,
h.name AS Referal,
h.id AS HealthOrgTypeId,
s.issuedate,
s.insertdate
FROM [DB1].[dbo].[exits] x
INNER JOIN [DB1].[dbo].[exitstates] s
ON x.id = s.exitid
INNER JOIN [DB1].[dbo].[healthorgtypes] h
ON x.healthorgtypeid = h.id
INNER JOIN [DB1].[dbo].[directions] d
ON x.directionid = d.id
INNER JOIN [DB1].[dbo].[healthcards] c
ON x.healthcardid = c.id
INNER JOIN [DB2].[pr].[table] p
ON p.id = c.tableid
INNER JOIN [DB3].[orgs].[organizations] g
ON g.id = x.organisationid
INNER JOIN [DB4].[dbo].exitstatetypes t
ON t.id = s.exitstatetypeid
WHERE s.id = (SELECT Max(es.id)
FROM exitstates es
WHERE es.exitid = x.id)
ORDER BY s.insertdate
Get row numbers, left outer join and set null row number value to -1 (like below, might have to fix it up a bit as I don't have a schema to work with):
;with RowNumber( ExitId, RowNumber )
as
(
SELECT
x.Id
, ROW_NUMBER() OVER (PARTITION BY s.ExitStateTypeId ORDER BY s.InsertDate)
FROM
[DB1].[dbo].[Exits] x
INNER JOIN [DB1].[dbo].[ExitStates] s
on x.Id = s.ExitId
WHERE
s.Id = (SELECT MAX(es.Id) from ExitStates es WHERE es.ExitId=x.Id)
and s.ExitStateTypeId in ( 4, 7 )
)
SELECT
ISNULL( rn.RowNumber, -1 ) AS Number
,x.Id
,p.FirstName
,p.LastName
,p.PN
,t.Name
,s.ExitStateTypeId as [Status]
,g.Name
,x.OrganisationId
,d.Name AS Direction
,d.Id AS DirectionId
,h.Name AS Referal
,h.Id AS HealthOrgTypeId
,s.IssueDate
,s.InsertDate
FROM [DB1].[dbo].[Exits] x
INNER JOIN [DB1].[dbo].[ExitStates] s on x.Id = s.ExitId
INNER JOIN [DB1].[dbo].[HealthOrgTypes] h on x.HealthOrgTypeId = h.Id
INNER JOIN [DB1].[dbo].[Directions] d on x.DirectionId = d.Id
INNER JOIN [DB1].[dbo].[HealthCards] c on x.HealthCardId = c.Id
INNER JOIN [DB2].[pr].[TABLE] p on p.Id = c.TABLEId
INNER JOIN [DB3].[orgs].[Organizations] g on g.Id = x.OrganisationId
INNER JOIN [DB4].[dbo].ExitStateTypes t on t.Id = s.ExitStateTypeId
left outer join RowNumber rn
on x.Id = rn.ExitId
WHERE s.Id = (SELECT MAX(es.Id) from ExitStates es WHERE es.ExitId=x.Id)
ORDER BY s.InsertDate

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 .