SSMS Query slow join - tsql

Tried to join three tables: car, car_and_engine, and engine. The second table, car_and_engine, connects the cars and their engines. A car type has up to three possible engine types. The query is significantly slower than expected (based on experience with similar operations in other languages). Is there anything terribly inefficient about this code?
select engine_type, AVG(horsepower) into #horsepower_by_engine_type
from TRANSPORT.dbo.engine
group by engine_type
go
with temp as(select * from TRANSPORT.dbo.car left join TRANSPORT.dbo.car_and_engine on TRANSPORT.dbo.car_and_engine.car_type_y = TRANSPORT.dbo.car.car_type_x)
select * from temp left join #horsepower_by_engine_type as e1 on temp.engine_type_1 = e1.engine_type
left join #horsepower_by_engine_type as e2 on temp.engine_type_2 = e2.engine_type
left join #horsepower_by_engine_type as e3 on temp.engine_type_3 = e3.engine_type

You don't really need a temp table (except when you are doing some diagnostics). You could replace your temp table syntax with an inline-view.
with temp as(select * from TRANSPORT.dbo.car left join TRANSPORT.dbo.car_and_engine on TRANSPORT.dbo.car_and_engine.car_type = TRANSPORT.dbo.car.car_type)
select * from temp left join
(select engine_type, AVG(horsepower)
from TRANSPORT.dbo.engine
group by engine_type) as e1 on temp.engine_type_1 = e1.engine_type
left join
(select engine_type, AVG(horsepower)
from TRANSPORT.dbo.engine
group by engine_type) as e2 on temp.engine_type_2 = e2.engine_type
left join
(select engine_type, AVG(horsepower)
from TRANSPORT.dbo.engine
group by engine_type) as e3 on temp.engine_type_3 = e3.engine_type
Better still, you could put your summary into your CTE
with temp as (select * from TRANSPORT.dbo.car left join TRANSPORT.dbo.car_and_engine on TRANSPORT.dbo.car_and_engine.car_type = TRANSPORT.dbo.car.car_type),
avgHP as (select engine_type, AVG(horsepower) from TRANSPORT.dbo.engine group by engine_type)
select * from temp left join avgHP as e1 on temp.engine_type_1 = e1.engine_type
left join avgHP as e2 on temp.engine_type_2 = e2.engine_type
left join avgHP as e3 on temp.engine_type_3 = e3.engine_type

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.

Why does not adding distinct in this query produce duplicate rows?

This query was taken from a Rails application log...I'm trying to edit a massive postgresql statement I didn't write....If I don't add a distinct keyword after the SELECT, 2 duplicate rows appear for each braintree account. Why is this and is there another way to avoid having to use the distinct to avoid duplicates?
EDIT: I understand what distinct is supposed to do, the reason I'm asking is that it doesn't generate duplicates for other toy lines. By other toy lines, this query is building a "table" for a particular toy id (this specific example toys.id = 12). How do I figure out where the duplicate rows are being generated?
SELECT accounts.braintree_account_id as braintree_account_id,
accounts.braintree_account_id as braintree_account_id, format('%s %s', addresses.first_name,
addresses.last_name) as shipping_address_full_name,
users.email as email, addresses.line_1 as shipping_address_line_1,
addresses.line_2 as shipping_address_line_2, addresses.city as
shipping_address_city, addresses.state as shipping_address_state,
addresses.zip as shipping_address_zip_code, addresses.country
as shipping_address_country, CASE WHEN xy_shirt IS NULL THEN '' ELSE xy_shirt END, plans.name as plan_name, toys.sku as sku, to_char(accounts.created_at, 'MM/DD/YYYY HH24:MM:SS') as
account_created_at,
to_char(accounts.next_assessment_at, 'MM/DD/YYYY HH24:MM:SS') as account_next_assessment_at,
accounts.account_status as account_status FROM \"accounts\" INNER JOIN \"addresses\" ON
\"addresses\".\"id\" = \"accounts\".\"shipping_address_id\" AND \"addresses\".\"type\" IN
('ShippingAddress') LEFT OUTER JOIN shipping_methods ON
shipping_methods.account_id = accounts.id LEFT OUTER JOIN plans ON
accounts.plan_id = plans.id
LEFT OUTER JOIN users ON
accounts.user_id = users.id LEFT OUTER JOIN toys ON plans.toy_id = toys.id
LEFT OUTER JOIN account_variations ON accounts.id =
account_variations.account_id LEFT OUTER JOIN variations ON
account_variations.variation_id = variations.id
LEFT OUTER JOIN
choice_value_variations ON variations.id =
choice_value_variations.variation_id
LEFT OUTER JOIN choice_values ON
choice_value_variations.choice_value_id = choice_values.id LEFT OUTER
JOIN choice_types ON choice_values.choice_type_id = choice_types.id
LEFT
OUTER JOIN choice_type_toys ON choice_type_toys.toy_id = toys.id
AND choice_type_toys.choice_type_id = choice_types.id
LEFT OUTER JOIN
(SELECT * FROM crosstab('SELECT accounts.id, choice_types.id,
choice_values.presentation FROM accounts\n
LEFT JOIN account_variations ON
accounts.id=account_variations.account_id\n
LEFT JOIN variations ON account_variations.variation_id=variations.id\n
LEFT JOIN choice_value_variations ON
variations.id=choice_value_variations.variation_id\n
LEFT JOIN choice_values ON
choice_value_variations.choice_value_id=choice_values.id\n
LEFT JOIN choice_types ON choice_values.choice_type_id=choice_types.id
ORDER BY 1,2',\n 'select distinct choice_types.id
from choice_types JOIN choice_values ON choice_values.choice_type_id =
choice_types.id JOIN choice_value_variations ON
choice_value_variations.choice_value_id = choice_values.id JOIN
variations ON choice_value_variations.variation_id = variations.id JOIN choice_type_toys ON choice_type_toys.choice_type_id = choice_types.id JOIN toys ON toys.id = choice_type_toys.toy_id
where toys.id=12 ORDER
BY choice_types.id ASC')\n
AS (account_id int, xy_shirt
VARCHAR)) account_variation_view\n ON
accounts.id=account_variation_view.account_id WHERE
\"accounts\".\"account_status\" = 'active' AND
\"addresses\".\"flagged_invalid_at\" IS NULL AND \"toys\".\"id\" = 12
AND (NOT EXISTS (SELECT \"account_skipped_months\".* FROM
\"account_skipped_months\" WHERE
\"account_skipped_months\".\"month_year\" = 'JUL2016' AND
(account_skipped_months.account_id = accounts.id)))"
The purpose of using DISTINCT in a SELECT statement is to eliminate duplicate rows.

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.

T-SQL Outer JOIN like oracle syntax (+)

I've to join 3 tables.
select u.*, c1.name, c2.name
users u, country c1, country c2
where u.country_id = c1.country_id(+)
AND u.bank_country_id = c2.country_id(+)
The symbol (+) in oracle means that I want a Left Outer Join on both that table (c1 and c2)
How to do the same in T-SQL?
select u.*, c1.name, c2.name
from users u
left outer join country c1 on u.country_id = c1.country_id
left outer join country c2 on u.bank_country_id = c2.country_id