Having this one:
code IN
(
SELECT DISTINCT aaa.code
FROM ORGHEADER AS aaa
LEFT JOIN ORGRELATEDPARTY AS bbb
ON aaa.oh_pk = bbb.parent
WHERE aaa.oh_pk NOT IN
(
SELECT fu.parent
FROM ORGRELATEDPARTY fu
WHERE fu.partytype = 'MNG'
)
)
Reading this one:
Changing IN to EXISTS in SQL
Tried to change it into "Exists", but produced this and it did not work:
code EXISTS
(
SELECT *
FROM ORGHEADER AS aaa
LEFT JOIN ORGRELATEDPARTY AS bbb
ON aaa.oh_pk = bbb.pr_oh_parent
WHERE aaa.oh_pk NOT IN
(
SELECT fu.parent
FROM ORGRELATEDPARTY fu
WHERE fu.pr_partytype = 'MNG'
)
WHERE code = DISTINCT aaa.oh_code
)
The error is 3706: Syntax error: expected something between '=' and 'DISTINCT' keyword.
You have already redundant code.
Inside the IN subquery you are selecting a column from ORGHEADER, so the LEFT join only adds noise since it returns in any case all rows from ORGHEADER.
Assuming that code belongs to a table aliased as t you can write the code with EXISTS like this:
WHERE EXISTS (
SELECT 1
FROM ORGHEADER AS aaa
WHERE aaa.oh_code = t.code
AND aaa.oh_pk NOT IN (
SELECT parent
FROM ORGRELATEDPARTY
WHERE pr_partytype = 'MNG'
)
)
Also, NOT IN will not work if the column parent of the table ORGRELATEDPARTY may return nulls.
I've been trying to understand the behavior of a query but i dont fully understand what is going on.
Take a look:
SELECT main.entity_id,main.sku,name.value AS name
FROM product_entity AS main
LEFT JOIN product_entity_varchar AS name ON main.entity_id = name.entity_id
WHERE name.attribute_id = (
SELECT attribute_id
FROM ger_attribute
WHERE attribute_code LIKE "name"
AND 'entity_type_id' = (
SELECT entity_type_id
FROM ger_entity_type
WHERE entity_type_code = 'catalog_product_info'
)
)
Can you please explain why it is using a subquery ,why the LEFT JOIN is important in these cases and the condition entity_type_code = 'catalog_product_info'?
Thanks
SELECT main.entity_id,main.sku,name.value AS name
FROM product_entity AS main
LEFT JOIN product_entity_varchar AS name ON main.entity_id = name.entity_id
...
The query starts by pulling out table product_entity. The LEFT JOIN allows the query to access the record(s) in table product_entity_varchar whose entity_id is equal to the value of the column that has the same name in product_entity.
In the resultset, the value of column value from table product_entity_varchar is displayed, under alias name.
The keyword LEFT makes the relation optional ; it there is no matching record in product_entity_varchar, the name will simply appear as NULL in the output. If it were an [INNER] JOIN, then the relation would be mandatory : unmatched records would be filtered out, and would not appear in the output.
OK. Let's clarify what is LEFT OUTER JOIN in SQL.
LEFT JOIN queries could be understood as just syntax abbreviation of UNION ALL of INNER JOIN-ed and NOT EXIST-ed queries.
Let's decompose LEFT JOIN-ed query:
SELECT main.entity_id,main.sku,name.value AS name
FROM
product_entity AS main
LEFT JOIN product_entity_varchar AS name ON main.entity_id = name.entity_id
WHERE
name.attribute_id = (
SELECT attribute_id
FROM ger_attribute
WHERE attribute_code LIKE "name"
AND 'entity_type_id' = (
SELECT entity_type_id
FROM ger_entity_type
WHERE entity_type_code = 'catalog_product_info'
)
)
Is equivalent to:
SELECT main.entity_id,main.sku,name.value AS name
FROM
product_entity AS main
JOIN product_entity_varchar AS name
ON main.entity_id = name.entity_id
WHERE
name.attribute_id = (
SELECT attribute_id
FROM ger_attribute
WHERE attribute_code LIKE "name"
AND 'entity_type_id' = (
SELECT entity_type_id
FROM ger_entity_type
WHERE entity_type_code = 'catalog_product_info'
)
)
UNION ALL
SELECT main.entity_id,main.sku, NULL AS name -- <-- Attention!
FROM
product_entity AS main
NOT EXISTS(
SELECT * FROM product_entity_varchar AS name
WHERE
main.entity_id = name.entity_id
AND name.attribute_id = (
SELECT attribute_id
FROM ger_attribute
WHERE attribute_code LIKE "name"
AND 'entity_type_id' = (
SELECT entity_type_id
FROM ger_entity_type
WHERE entity_type_code = 'catalog_product_info'
)
)
)
I hope this will help to understand query, although it's impossible without data to answer "why it is using a subquery" etc.
SELECT *
FROM TBDA temp
LEFT JOIN (
SELECT
(
COALESCE (
(
SELECT sum_payment
FROM TBDA_REPAYMENT
WHERE isdn = temp.isdn
AND tr_month = temp.tr_month
AND tr_year = temp.tr_year
),
(
SELECT sum_payment
FROM TBDA_PAYNEW
WHERE isdn = temp.isdn
AND tr_month = temp.tr_month
AND tr_year = temp.tr_year
)
)
)
)
TBDA table has isdn,tr_month,tr_year
TBDA_REPAYMENT table has isdn,tr_month,tr_year,sum_payment
TBDA_PAYNEW table has isdn,tr_month,tr_year,sum_payment
Expected result :
A table off all fields of TBDA with sum_payment, look for sum_payment from two tables (TBDA_REPAYMENT & TBDA_PAYNEW) by ISDN (TBDA table) by comparing isdn,tr_month,tr_year, if sum_payment exists in one of two tables (TBDA_REPAYMENT & TBDA_PAYNEW) then add it to the results, otherwise it's null.
I get the error :
[Err] 42000 - [SQL Server]Incorrect syntax near ')'.
SELECT
*
FROM
TBDA temp
Cross Apply ( SELECT COALESCE (
(
SELECT
sum_payment
FROM
TBDA_REPAYMENT
WHERE
isdn = temp.isdn
AND tr_month = temp.tr_month
AND tr_year = temp.tr_year
),
(
SELECT
sum_payment
FROM
TBDA_PAYNEW
WHERE
isdn = temp.isdn
AND tr_month = temp.tr_month
AND tr_year = temp.tr_year
)
) as First_Null_Value
) as value_table
Unless a CROSS JOIN, CROSS APPLY or OUTER APPLY is used, the ON clause is required.
Hence the error.
Although you could still do something like ... LEFT JOIN othertable ON (1=1).
But you could re-write this query using 2 left joins.
select
temp.*,
coalesce(repay.sum_payment, paynew.sum_payment) as value_table
from TBDA temp
left join TBDA_REPAYMENT repay on (repay.isdn = temp.isdn and repay.tr_month = temp.tr_month and repay.tr_year = temp.tr_year)
left join TBDA_PAYNEW paynew on (paynew.isdn = temp.isdn and paynew.tr_month = temp.tr_month and paynew.tr_year = temp.tr_year);
Note that there's an assumption that the tables TBDA_REPAYMENT & TBDA_PAYNEW have a uniqueness on the 3 fields used in the join (isdn, tr_month, tr_year).
Or the OUTER APPLY syntax could be used.
And if there's no uniqueness on (isdn, tr_month, tr_year) then you can use that to SUM the total at the same time.
select
temp.*, repay.sum_payment as repay_sum_payment, paynew.sum_payment as paynew_sum_payment,
coalesce(repay.sum_payment, paynew.sum_payment) as value_table
from TBDA temp
outer apply
(
select nullif(sum(rp.sum_payment),0) as sum_payment
from TBDA_REPAYMENT rp
where rp.isdn = temp.isdn
and rp.tr_month = temp.tr_month
and rp.tr_year = temp.tr_year
) as repay
outer apply
(
select nullif(sum(pn.sum_payment),0) as sum_payment
from TBDA_PAYNEW pn
where pn.isdn = temp.isdn
and pn.tr_month = temp.tr_month
and pn.tr_year = temp.tr_year
) as paynew;
Example Snippet:
declare #TBDA table (isdn int, tr_month int, tr_year int);
declare #TBDA_REPAYMENT table (isdn int, tr_month int, tr_year int, sum_payment int);
declare #TBDA_PAYNEW table (isdn int, tr_month int, tr_year int, sum_payment int);
insert into #TBDA (isdn, tr_month, tr_year) values (1,6,2018),(2,6,2018);
insert into #TBDA_REPAYMENT (isdn, tr_month, tr_year, sum_payment) values (1,6,2018, 100);
insert into #TBDA_PAYNEW (isdn, tr_month, tr_year, sum_payment) values (1,6,2018, 200),(2,6,2018,100),(2,6,2018,200);
--
-- Using left join
--
select
temp.*, repay.sum_payment, paynew.sum_payment,
coalesce(repay.sum_payment, paynew.sum_payment) as value_table
from #TBDA temp
left join #TBDA_REPAYMENT repay on (repay.isdn = temp.isdn and repay.tr_month = temp.tr_month and repay.tr_year = temp.tr_year)
left join #TBDA_PAYNEW paynew on (paynew.isdn = temp.isdn and paynew.tr_month = temp.tr_month and paynew.tr_year = temp.tr_year);
--
-- Using outer apply
--
select
temp.*, repay.sum_payment as repay_sum_payment, paynew.sum_payment as paynew_sum_payment,
coalesce(repay.sum_payment, paynew.sum_payment) as value_table
from #TBDA temp
outer apply
(
select nullif(sum(rp.sum_payment),0) as sum_payment
from #TBDA_REPAYMENT rp
where rp.isdn = temp.isdn
and rp.tr_month = temp.tr_month
and rp.tr_year = temp.tr_year
) as repay
outer apply
(
select nullif(sum(pn.sum_payment),0) as sum_payment
from #TBDA_PAYNEW pn
where pn.isdn = temp.isdn
and pn.tr_month = temp.tr_month
and pn.tr_year = temp.tr_year
) as paynew;
Error is due to not specifying ON condition on LEFT JOIN.
LEFT JOIN without ON will throw an error.
If you don't want to specify any condition, try CROSS JOIN
Just use correlated subqueries:
SELECT t.*,
IFNULL ( (SELECT r.sum_payment
FROM TBDA_REPAYMENT r
WHERE r.isdn = t.isdn AND
r.tr_month = t.tr_month AND
r.tr_year = t.tr_year
),
(SELECT p.sum_payment
FROM TBDA_PAYNEW p
WHERE p.isdn = t.isdn AND
p.tr_month = t.tr_month AND
p.tr_year = t.tr_year
)
)
)
FROM TBDA t;
Although you can use APPLY, the use of SELECT is already insisting that at most one row be returned from the subqueries.
Also note a couple of things. First, I replaced COALESCE() with IFNULL(). Although I much prefer COALESCE() (because it is the standard and more flexible), the code is more efficient with IFNULL(). COALESCE() causes SQL Server to evaluate the first argument twice when it is not NULL.
Second, table aliases and qualified column names should be used everywhere in the query.
IS it possible to return the table of a With-Statement from an inline-table valued function?
my With-Statement looks like this
WITH ret AS(
SELECT t.ID
FROM SelfReferencingTable
WHERE ID = #PartnerID
UNION ALL
SELECT t.ID
FROM (SelfReferencingTable) t INNER JOIN
ret r ON t.ParentID = r.ID
)
Yes, you can. You just have to place the common table expression (what you refer to as a WITH statement) in the appropriate place:
create function TT()
RETURNS TABLE
AS
RETURN (With Aardvark as (select * from sysobjects) --TODO - Remove *, use column names
select * from Aardvark)
;
i need to select vbeln from likp and i have to select only vbeln that has been marked 'C' in vbuk. and from that likp-vbeln(delivery) i have to search/select for its carrier in vekp and after searching for the carrier I then have to search/select its shiptype from another table. i have table with 7 fields, in the code below im selecting some deliveries but i dont know how to add the condition in vbuk table because i dont need to select from vbuk. thanks. the code is below:
SELECT likp~vbeln
tab~shiptype
vekp~carrier
vekp~service
COUNT( DISTINCT vekp~shipment )
SUM( vekp~packagecount )
SUM( vekp~rate ) FROM vekp
INNER JOIN tab
ON tab~carrier = vekp~carrier INNER JOIN likp
ON vekp~delivery = likp~vbeln INTO itab
WHERE likp~erdat IN so_date AND
vekp~delivery = likp~vbeln AND
vekp~carrier = tab~code
GROUP BY vbeln shiptype carrier service.
You don't need to select from the table in order to join on it, just add VBUK to your join.
I notice that you haven't included an INTO clause, which is needed when you use a field-list.
Something like:
SELECT likp~vbeln
tab~shiptype
vekp~carrier
vekp~service
COUNT( DISTINCT vekp~shipment )
SUM( vekp~packagecount )
SUM( vekp~rate )
INTO (field1, fied2, etc) "<=== Change1
FROM vekp
INNER JOIN tab
ON tab~carrier = vekp~carrier INNER JOIN likp
ON vekp~delivery = likp~vbeln INTO itab
INNER JOIN VBUK "<=== Change2
ON likp~vbeln = vbuk~vbeln
WHERE likp~erdat IN so_date AND
vekp~delivery = likp~vbeln AND
vekp~carrier = tab~code AND
vbuk~fieldtocheck = 'C' "<=== Change3
GROUP BY vbeln shiptype carrier service.