Rewrite Query with Cartesian product - tsql

I am not a developer, so need help in rewriting this Query without a inner join as i think that is the core issue. This runs over 20 seconds. Smaller chunks run in under a second. Pl help.
select a.compID, b.InitialRT, b.VwRgts, b.UpdRgts, b.InsRgts, b.delRgts, b.Sscrnum , c.UserID
from tablecmpy a, tbldetrght b (nolock)
inner join tableuser c (nolock) on c.GroupID = b.UserId
where b.RecType='G'
and b.compID='[ALL]'
and b.InitialRT+b.VwRgts+b.UpdRgts+b.InsRgts+b.delRgts > 0

You already got Cartesian join (old style joins) here from tablecmpy a, tbldetrght b (nolock). Try to use:
SELECT a.compID,
b.InitialRT,
b.VwRgts,
b.UpdRgts,
b.InsRgts,
b.delRgts,
b.Sscrnum,
c.UserID
FROM tablecmpy a (nolock)
CROSS JOIN tbldetrght b (nolock)
INNER JOIN tableuser c (nolock)
ON c.GroupID = b.UserId
WHERE b.RecType='G'
AND b.compID='[ALL]'
AND COALESCE(b.InitialRT,0) +
COALESCE(b.VwRgts,0) +
COALESCE(b.UpdRgts,0) +
COALESCE(b.InsRgts,0) +
COALESCE(b.delRgts,0) > 0
I don't know if you have NULL in b.columns, so I add COALESCE to handle them.

Related

postgres error 42803 with subquery and group by

Hi all postgres developer,
below code can run success
select p.* from
(select p.*, count(distinct p1.id) n from TMB p
left join TMB p1 on p.id = p1.pid
left join TUR u on p.id = any(u.jks)
group by p.id) p
join TUR u on u.id = p.uid
but, below code with error message
[42803] ERROR: column "p.xxxx" must appear in the GROUP BY clause or be used in an aggregate function
select p.* from
(select p.*, count(distinct p1.id) n from (select * from TMB) p
left join TMB p1 on p.id = p1.pid
left join TUR u on p.id = any(u.jks)
group by p.id) p
join TUR u on u.id = p.uid
I want to do some where filter on TMB table before left join, so I think can speed up left join.
I think (select * from TMB) is a subquery equal as TMB. I can not understand why this error message. anyone can tell me detail?
The difference is that without the subquery, PostgreSQL can deduce that id is the primary key of tmb, so you need not add all columns of tmb to the GROUP BY clause. With the subquery, PostgreSQL cannot make that deduction, so you have to add all columns.

postgresql inner join duplicating some records

I have a large query developed as cte, in certain parts I have to make totals of secondary tables using inner joins to minimize the number of records processed, somehow two subqueries almost identical one works and the second duplicates 8 times some of the totalized records
I need to use inner join or the response time is shoots to the sky by 15x or more times
with
p0 as (select distinct on (pventa) pventa, p.tipo tpva from lecturas l
left join puntoventa p on l.pventa=p.numero where dia between '2017-10-01' and '2017-10-31' and p.tipo in ('A','E')),
r1 as (select p.tpva, l.pventa, dia, turno from lecturas l
inner join p0 p on p.pventa=l.pventa
where dia between '2017-10-01' and '2017-10-31'),
p1 as (select pva, remision, sum(abono), count(abono) from pagosremisiones p
inner join movsgas m on p.pva=m.pventa and p.remision=m.folio
inner join r1 r on r.pventa=m.pventa and r.dia=m.dia and r.turno=m.turno group by 1,2 order by 1,2 ),
f1 as (select c.serie, c.factura, sum(abono), count(abono) from chequefactura c
inner join movsgas m on c.serie=m.serie and c.factura=m.factura
inner join r1 r on r.pventa=m.pventa and r.dia=m.dia and r.turno=m.turno group by 1,2 order by 1,2 )
select * from p1
Nprem and ncheck are for debugging
P1 and f1 depend on r1, p1 works (as far as I've tried) without duplicate records (nprem corresponds to existing registers), however, ncheck increases on some records up to 8 times its actual values
I'm not sure if the correct p1's results are purely casual and don't know how to correct duplicates in f1
I do have the alternative of doing direct subqueries but I have a didactic interest in using joins
Btw, so far direct subqueries are much more efficient than the joins possibly because they have been poorly structured
What am I doing wrong?
What would you do to optimize the code?
Thanks in advance
Jose
the trick needed is the new subquery r2 including [ distinct on (serie, factura) ], if I omit it the error persists; duplicates in r2 do not correspond to the number of duplicates in f1, so I had no idea where so many came from; thank you all and again an apology for the terrible description of my problem
with
p0 as (select distinct on (pventa) pventa, p.tipo tpva from lecturas l
left join puntoventa p on l.pventa=p.numero where dia between '2017-10-01' and '2017-10-31' and p.tipo in ('A','E')),
r1 as (select p.tpva, l.pventa, dia, turno from lecturas l
inner join p0 p on p.pventa=l.pventa
where dia between '2017-10-01' and '2017-10-31'),
r2 as (select distinct on (serie, factura) m.serie,m.factura from movsgas m
inner join chequefactura c on c.serie=m.serie and c.factura=m.factura
inner join r1 r on r.pventa=m.pventa and r.dia=m.dia and r.turno=m.turno),
p1 as (select pva, remision, sum(abono) payp from pagosremisiones p
inner join movsgas m on p.pva=m.pventa and p.remision=m.folio
inner join r1 r on r.pventa=m.pventa and r.dia=m.dia and r.turno=m.turno group by 1,2 order by 1,2 ),
f1 as (select c.serie, c.factura, sum(abono) payfr2, count(*) from chequefactura c
inner join r2 r on r.serie=c.serie and r.factura=c.factura group by 1,2 order by 1,2 )

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 .