DB2: group by interfering subquery in Select clause - select

I'm stuck with a SQL query. I'm making a subquery in the select clause and db2 prompts a -119 error telling:
"An expression starting with "FACILITY_ID" specified in a SELECT clause, HAVING clause, or ORDER BY clause is not specified in the GROUP BY clause or it is in a SELECT clause, HAVING clause, or ORDER BY clause with a column function and no GROUP BY clause is specified. SQL Code: -119, SQL State: 42803"
I don't know how to include NUMTAGS in the GROUP BY. I tried including the BC.ITEM in the GROUP BY clause with no result. I don't know how exactly to look for this in the web, and the forums I looked at were no useful.
If someone could explain me how to mend this or paste a link where I could look for a solution, I would be grateful.
The SQL query is with DB2 and it's down here:
SELECT SS.NAME, B.DESTINATION_ID, P.DESCRIPTION, B.LAST_READ_DATE, B.LABEL,
(SELECT COUNT(BC.ITEM)
FROM PROJECT_DB.BOX_CONTENT BC
WHERE BC.FACILITY_ID = B.FACILITY_ID
AND BC.BOX_ID = B.BOX_ID
GROUP BY BC.ITEM) AS NUMTAGS,
B.BOX_ID
FROM PROJECT_DB.BOX B
INNER JOIN MAINDB.DESTINATION P ON B.DESTINATION_ID = P.DESTINATION_ID
INNER JOIN MAINDB.WAREHOUSE_DESTINATION_SECTION WH
ON B.DESTINATION_ID = WH.DESTINATION_ID
AND B.WAREHOUSE_ID = WH.WAREHOUSE_ID
INNER JOIN MAINDB.SECTION S ON S.SECTION = WH.SECTION
AND S.SECTION_TYPE = B.SECTION_TYPE
INNER JOIN MAINDB.DESTINATION_SET SS
ON SS.DESTINATION_SET_ID = S.DESTINATION_SET_ID
WHERE B.WAREHOUSE_ID = 100
GROUP BY B.BOX_ID, B.FACILITY_ID, B.DESTINATION_ID, B.LAST_READ_DATE, B.LABEL, P.DESCRIPTION, SS.NAME

You can correct the statement by: v including the columns in the GROUP
BY clause that are in the SELECT clause, or v removing the columns
from the SELECT clause.
From: DB2 documentation.
You need to put ALL selected columns in your GROUP BY...

Since you're using a scalar sub-select, I don't think you need a GROUP BY clause on either of your statements. Try this:
SELECT
SS.NAME,
B.DESTINATION_ID,
P.DESCRIPTION,
B.LAST_READ_DATE,
B.LABEL,
(SELECT COUNT(BC.ITEM)
FROM PROJECT_DB.BOX_CONTENT BC
WHERE BC.FACILITY_ID = B.FACILITY_ID
AND BC.BOX_ID = B.BOX_ID
) AS NUMTAGS,
B.BOX_ID
FROM PROJECT_DB.BOX B
JOIN MAINDB.DESTINATION P
ON B.DESTINATION_ID = P.DESTINATION_ID
JOIN MAINDB.WAREHOUSE_DESTINATION_SECTION WH
ON B.DESTINATION_ID = WH.DESTINATION_ID
AND B.WAREHOUSE_ID = WH.WAREHOUSE_ID
JOIN MAINDB.SECTION S
ON S.SECTION = WH.SECTION
AND S.SECTION_TYPE = B.SECTION_TYPE
JOIN MAINDB.DESTINATION_SET SS
ON SS.DESTINATION_SET_ID = S.DESTINATION_SET_ID
WHERE B.WAREHOUSE_ID = 100

My final working query is this down here. I think I had the wrong tables referenced at the "group by" or something similar:
SELECT SS.NAME, P.DESTINATION_ID, P.DESCRIPTION, B.LAST_READ_DATE, B.LABEL,
(SELECT COUNT(BC.ITEM)
FROM PROJECT_DB.BOX_CONTENT BC
WHERE BC.ID_FACILITY = B.ID_FACILITY
AND BC.ID_BOX = B.ID_BOX
GROUP BY BC.ITEM) AS NUMTAGS,
B.BOX_ID, B.FACILITY_ID
FROM PROJECT_DB.BOX B
INNER JOIN MAINDB.DESTINATION P ON B.DESTINATION_ID = P.DESTINATION_ID
INNER JOIN MAINDB.WAREHOUSE_DESTINATION_SECTION WH
ON WH.WAREHOUSE_ID = B.WAREHOUSE_ID
AND WH.ID_DESTINATION = B.ID_DESTINATION
INNER JOIN MAINDB.SECTION S ON S.SECTION = WH.SECTION
AND S.SECTION_TYPE = B.SECTION_TYPE
INNER JOIN MAINDB.DESTINATION_SET SS ON SS.DESTINATION_SET_ID = S.DESTINATION_SET_ID
WHERE B.WAREHOUSE_ID = 100
GROUP BY B.BOX_ID, B.FACILITY_ID, P.DESTINATION_ID, B.LAST_READ_DATE, B.LABEL, P.DESCRIPTION, SS.NAME
WITH UR

Related

PostgreSQL Inner Join Where Get IDs of 3 Products

I have these 5 tables which is sale_order directly connected to sale_order_line that has the products of the order of course which is connected to product_product that is connected to product_template where a table called mrp_bom can connect to product template and a table connected to it which is bom_line. I am trying to Output the products that contain the word 836g
Here is what I have so far:
Select so.name,
pt.name,
sol.name
From sale_order so
Inner Join sale_order_line sol
On so.id = sol.order_id
Inner Join product_template pt
On sol.product_id = pt.id
Inner Join mrp_bom bom
On pt.id = bom.product_tmpl_id
Inner Join mrp_bom_line boml
On bom.id = boml.bom_id
Where boml.product_id = (Select id From product_template Where name Like '%836g%'
Order By so.name
This code outputs an error because I have 3 items with 836g. I tried changing the = in the condition into IN so it will grab all the ids it will return. But still it's giving me an error. This is the best I have so far, I have tried so many times, but I can't figure it out.
I have the feeling that something along these lines is what you actually want:
SELECT so.name,
pt.name,
sol.name
FROM sale_order so
INNER JOIN sale_order_line sol
ON so.id = sol.order_id
INNER JOIN product_template pt
ON sol.product_id = pt.id
INNER JOIN mrp_bom bom
ON pt.id = bom.product_tmpl_id
INNER JOIN mrp_bom_line boml
ON bom.id = boml.bom_id
WHERE pt.name LIKE '%836g%' -- just add a WHERE condition directly in your query
ORDER BY so.name
OMG! I just had the answer. I don't think this will help anyone but i'll post the answer i have
SELECT so.name,
pt.name PT,
sol.name SOL,
(Select pp1.name_template From product_product pp1 Where boml.product_id = pp1.id) BOML,
boml.product_id
FROM sale_order so
INNER JOIN sale_order_line sol
ON so.id = sol.order_id
INNER JOIN product_template pt
ON sol.product_id = pt.id
INNER JOIN mrp_bom bom
ON pt.id = bom.product_tmpl_id
INNER JOIN mrp_bom_line boml
ON bom.id = boml.bom_id
WHERE (Select pp1.name_template From product_product pp1 Where boml.product_id = pp1.id) LIKE '%836g%'
ORDER BY so.name
Thank you all for the effort of helping me! Great community we got here! :D

Lateral query syntax

I'm trying to get lateral to work in a Postgres 9.5.3 query.
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id",
lateral (select ci."MaximumPlaces" - "EnrolledStudents") x
I want the right-most column to be the result of "MaximumPlaces" - "EnrolledStudents" for that row but am struggling to get it to work. At the moment PG is complaining that "EnrolledStudents" does not exist - which is exactly the point of "lateral", isn't it?
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
lateral (select "MaximumPlaces" - "EnrolledStudents") as "x"
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id"
If I try inlining the lateral clause (shown above) in the select it gets upset too and gives me a syntax error - so where does it go?
Thanks,
Adam.
You are missing the point with LATERAL. It can access columns in tables in the FROM clause, but not aliases defined in SELECT clause.
If you want to access alias defined in SELECT clause, you need to add another query level, either using a subquery in FROM clause (AKA derived table) or using a CTE (Common Table Expression). As CTE in PostgreSQL acts as an optimization fence, I strongly recommend going with subquery in this case, like:
select
-- get all columns on the inner query
t.*,
-- get your new expression based on the ones defined in the inner query
t."MaximumPlaces" - t."EnrolledStudents" AS new_alias
from (
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id"
) t

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

sql, group a query with no aggregations and multiple tables

I need to group the query below by dda.LA and need to display all the columns listed in the select but almost none of them are aggregated. i don't know what the syntax to get around this is and i can not find a post that shows this syntax (most examples only have one table, two at tops).
Select dda.a,
dda.b,
dda.c,
dda.d,
dda.e,
dda.f,
dda.g,
dda.h,
dda.i,
dda.j,
dda.k,
dda.l,
dda.m,
dda.n,
dda.o,
dda.p,
dda.r,
dda.u,
dda.LA,
dd.aa,
coalesce(apn.apn,Pt.z) as abc,
coalesce(apn.v,Pt.y) as def,
'RFN' RowFocusIndicator ,
'SRI' SelectRowIndicator ,
'Y' Expanded ,
Convert(Int, Null) SortColumn
From dda (NoLock)
Inner Join dd (NoLock) On dda.d = dd.q and dda.e = dd.e
Left Outer Join apn (nolock) on dda.r = apn.r
Left Outer Join Pt (nolock) on dda.s = Pt.t
Where 1 = 1
And dda.u = (Select Min(c.w)
From c (NoLock)
Where c.x = dda.s)
Thanks!
Just add this to any column that you want to aggregate by:
AggregatedColumnName = Aggregation(fieldToAggregate) Over (Partition By dda.LA)
ex.
aCount = Count(dda.a) Over (Partition By dda.LA)

Why do these two queries return a different number of rows

I'm using adventureworks2012:
The first query returns 43 rows and no nulls, whereas the second returns over 19 thousand and lots of nulls.
I thought an outer join returned rows from the left side of the query even if the condition is not met, and therefore the two queries should be equivalent?
--1
SELECT c.CustomerID, s.SalesOrderID, s.OrderDate
FROM Sales.Customer AS c
LEFT OUTER JOIN Sales.SalesOrderHeader AS s ON c.CustomerID = s.CustomerID
WHERE s.OrderDate = '2005/07/01';
--2
WITH orders AS (
SELECT SalesOrderID, CustomerID, OrderDate
FROM Sales.SalesOrderHeader
WHERE OrderDate = '2005/07/01'
)
SELECT c.CustomerID, orders.SalesOrderID, orders.OrderDate
FROM Sales.Customer AS c
LEFT OUTER JOIN orders ON c.CustomerID = orders.CustomerID
ORDER BY orders.OrderDate DESC;
It's because of WHERE clause in query 1. The WHERE clause filters the final result of the two tables being joined. You need to move the condition from WHERE clause into ON, which filters the records (on table Sales.SalesOrderHeader) first before joining it to another table (Sales.Customer), you can also find it here.
SELECT c.CustomerID, s.SalesOrderID, s.OrderDate
FROM Sales.Customer AS c
LEFT OUTER JOIN Sales.SalesOrderHeader AS s
ON c.CustomerID = s.CustomerID AND
s.OrderDate = '2005/07/01';
You are killing the outer in the first by referencing a table in the where
Just move that condition into the join
SELECT c.CustomerID, s.SalesOrderID, s.OrderDate
FROM Sales.Customer AS c
LEFT OUTER JOIN Sales.SalesOrderHeader AS s
ON c.CustomerID = s.CustomerID
AND s.OrderDate = '2005/07/01';