selecting in 4 tables with conditions - abap

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.

Related

Multiple Joins less cost way

Below query has 3 tables where I have to do 2 joins to get a column information, It is very slow, is there any effective way to run this query?
SELECT DISTINCT
st.status_c1
FROM
schemaname.tablea st
INNER JOIN (
SELECT
lic.SpecId AS applicationid,
lic.comData AS combusappid,
lic.ageId,
lic.licId,
lic.licid,
lic.appid,
com.nybe_bustbl_id AS busid
FROM
schemaname.tableb lic
INNER JOIN tablec com ON lic.comData = com.comData
WHERE
lic.ageId = '12'
) rt ON
st.ageId = rt.ageId
AND
st.licId = rt.licId
AND
st.licid = rt.licid
AND
st.appid = rt.appid
WHERE
status_id = 3;
Your current query will create extra rows when the JOIN condition is met for multiple entries in either table and then DISTINCT will filter these duplicates out. You could try to cut down the amount of work filtering duplicates by using EXISTS:
SELECT DISTINCT
st.status_c1
FROM schemaname.tablea st
WHERE status_id = 3
AND EXISTS (
SELECT 1
FROM schemaname.tableb lic
WHERE lic.ageId = '12'
AND st.ageId = lic.ageId
AND st.licId = lic.licId
AND st.appid = lic.appid
AND EXISTS(
SELECT 1 FROM tablec com WHERE lic.comData = com.comData
)
);
There is a bunch of redundancy in the query (licid is in the SELECT and ON twice) and you don't need to use subqueries for this. I think this will work:
SELECT DISTINCT st.status_c1
FROM tablea st
INNER JOIN tableb lic ON st.ageId = lic.ageId
AND st.licId = lic.licId
AND st.appid = lic.appid
INNER JOIN tablec com ON lic.comData = com.comData
WHERE status_id = 3
and lic.ageId = '12'
How frequently are you going to run this query, how much time is it taking now and what is the explectation. Are statistcs run on all tha tables.
There are many things which we can think of, but to start with if possible could you plese give ue the like the table structure and explain plan of the query.
Also may be an index on status_c1 table tablea help. As pointed out try removing the join condition which is twice AND st.licid = rt.licid
SELECT DISTINCT st.status_c1
FROM schemaname.tablea st
INNER JOIN (
SELECT
lic.SpecId AS applicationid, lic.comData AS combusappid, lic.ageId, lic.licId, lic.licid,
lic.appid, com.nybe_bustbl_id AS busid
FROM schemaname.tableb lic
INNER JOIN tablec com ON lic.comData = com.comData
WHERE lic.ageId = '12'
) rt ON st.ageId = rt.ageId AND st.licId = rt.licId AND st.licid = rt.licid AND st.appid = rt.appid
WHERE status_id = 3;

Trying to understand a query (LEFT JOIN and subquery)

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.

SQL Server Slow query using subqueries

I have a very slooowwwww query.
It selects customer records, with combined criteria, kinda like this:
A table has Customers, another table has CustomerCars, another table has CustomerMotorcycles.
A customer can have one or more cars. If the customer is a commercial business and any one of the customer's cars is a Ford, then we want to exclude that customer from our selection.
A customer can also have one or more motorcycles, and if the customer is a retail business and any one of its motorcycles is a Harley, then we want to exclude that customer.
So I have a statement like:
SELECT *
FROM CUST
WHERE
(CUST.CUSTTYPE = 'COMM'
AND CUST.CUSTID NOT IN (SELECT CUSTCARS.CUSTID
FROM CUSTCARS
WHERE CUSTCARS.CAR = 'FORD'))
OR
(CUST.CUSTTYPE = 'RETAIL'
AND CUST.CUSTID NOT IN (SELECT CUSTCYCLES.CUSTID
FROM CUSTCYCLES
WHERE CUSTCYCLES.CYCLE = 'HARLEY'))
This runs crazy slow.
This is currently being run as a bunch of separate queries that dump data into temporary tables, then several other queries are run to delete the records we don't want, but it's quite clumsy.
Any suggestions? Thanks for any help!
Try "left excluding joins", where we left join the data that matches the conditions we do not want, and then exclude the matching rows through the where clause:
SELECT
CUST.*
FROM CUST
LEFT JOIN CUSTCARS ON CUST.CUSTID = CUSTCARS.CUSTID
AND CUSTCARS.CAR = 'FORD'
AND CUST.CUSTTYPE = 'COMM'
LEFT JOIN CUSTCYCLES ON CUST.CUSTID = CUSTCYCLES.CUSTID
AND CUSTCYCLES.CYCLE = 'HARLEY'
AND CUST.CUSTTYPE = 'RETAIL'
WHERE CUSTCARS.CUSTID IS NULL
OR CUSTCYCLES.CUSTID IS NULL
;
Whilst I'm here, it might be the OR in your existing query that causes excessive slowness (maybe) so perhaps combining the 2 subqueries to one list would help:
SELECT
*
FROM CUST
WHERE CUSTID NOT IN (
SELECT
CUSTCARS.CUSTID
FROM CUSTCARS
INNER JOIN CUST ON CUSTCARS.CUSTID = CUST.CUSTID
WHERE CUSTCARS.CAR = 'FORD'
AND CUST.CUSTTYPE = 'COMM'
UNION ALL
SELECT
CUSTCYCLES.CUSTID
FROM CUSTCYCLES
INNER JOIN CUST ON CUSTCYCLES.CUSTID = CUST.CUSTID
WHERE CUSTCYCLES.CYCLE = 'HARLEY'
AND CUST.CUSTTYPE = 'RETAIL'
)
;
Two things come to mind. First, make sure there are indexes for CUSTCARS.CAR and CUSTCYCLES.CYCLE. Second, you might try NOT EXISTS instead of NOT IN.
SELECT * FROM CUST
WHERE
(CUST.CUSTTYPE = 'COMM'
AND NOT EXISTS(SELECT 1 FROM CUSTCARS WHERE CUSTCARS.CAR = 'FORD'
AND CUSTCARS.CUSTID=CUST.CUSTID))
OR
(CUST.CUSTTYPE = 'RETAIL'
AND NOT EXISTS(SELECT 1 FROM CUSTCYCLES WHERE CUSTCYCLES.CYCLE = 'HARLEY'
AND CUSTCYCLES.CUSTID=CUST.CUSTID))
I would suggest starting with not exists:
select c.*
from cust c
where not (c.custtype = 'COMM' and
exists (select 1
from custcars cc
where cc.custid =c.custid and cc.car = 'FORD'
)
) and
not (c.custtype = 'RETAIL' and
exists (select 1
from custcycles cc
where cc.custid = c.custid and cc.cycle = 'HARLEY'
)
) ;
Then, you want to be sure you have indexes on custcar(custid, car) and custcycles(custid, cycle).

Oracle Nested Select returns ORA-00913 "too many values"

I get the ORA-00913: "too many values" error while nesting a pivot sql into another sql.
How can I correct this or is there a simpler way to write this as I need the "NEEDTHISFIELD" field for another program.
SELECT null as NEEDTHISFIELD, (SELECT * FROM(
SELECT th.BUCHDAT,th.OID,th.EFTYP,ef.NAME,thp.XORDER,thp.THEVALUE
FROM THISTORY th
LEFT JOIN EFTYP ef on th.EFTYP = ef.OID
LEFT JOIN THPARA thp on th.OID = thp.THISTORY
WHERE th.EFTYP = 'xyz'
)
PIVOT (MAX(THEVALUE) FOR (XORDER) IN (
'100' AS "VAL1",
'101' AS "VAL2"
)))
FROM DUAL;
Many thanks!
Your nested query return more that one record.
Try something like this
SELECT null as NEEDTHISFIELD,t.* FROM(
SELECT th.BUCHDAT,th.OID,th.EFTYP,ef.NAME,thp.XORDER,thp.THEVALUE
FROM THISTORY th
LEFT JOIN EFTYP ef on th.EFTYP = ef.OID
LEFT JOIN THPARA thp on th.OID = thp.THISTORY
WHERE th.EFTYP = 'xyz'
)
PIVOT (MAX(THEVALUE) FOR (XORDER) IN (
'100' AS "VAL1",
'101' AS "VAL2"
) t ;
Just include an alias for the pivoted table then you can add it the required field to the list of selected fields:
SELECT t.*,
NULL AS NeedThisField
FROM ( SELECT th.BUCHDAT,
th.OID,
th.EFTYP,
ef.NAME,
thp.XORDER,
thp.THEVALUE
FROM THISTORY th
LEFT JOIN EFTYP ef on th.EFTYP = ef.OID
LEFT JOIN THPARA thp on th.OID = thp.THISTORY
WHERE th.EFTYP = 'xyz'
)
PIVOT (
MAX(THEVALUE)
FOR (XORDER) IN ( '100' AS "VAL1", '101' AS "VAL2" )
) t;

SQL SHOW one more column name FROM operator in

I need to show columns from IN
operator
My query is :
SELECT prizes.type,prizes.name
FROM lottery_payment_prizes payment
JOIN lottery_prizes prizes ON
prizes.id = payment.prize_id
WHERE payment.payment_id IN
(( SELECT id FROM lottery_payments
WHERE lottery_id = (SELECT id FROM lotteries WHERE abbr = 'TR' AND group_id = '3' )))
Result is:
My question : How can show two columns from lottery_payments ,
lottery_payments returns only ID to IN operator
function.I need to show column name "place" from lottery_payemnts table.
Thanks all.
If you need to columns from lottery_payments, you need to add a join to it:
SELECT payments.place, payments.id, prizes.type, prizes.name
FROM lottery_payment_prizes payment
JOIN lottery_prizes prizes ON
prizes.id = payment.prize_id
JOIN lottery_payments payments ON
payment.payment_id = payments.id
WHERE lottery_id = (SELECT id FROM lotteries WHERE abbr = 'TR' AND group_id = '3' )
Instead of using IN You should use join
SELECT prizes.type,prizes.name
FROM
lottery_payment_prizes payment
JOIN
lottery_prizes prizes ON prizes.id = payment.prize_id
JOIN lottery_payments lp ON payment.payment_id = lp.id
WHERE lp.lottery_id = (SELECT id FROM lotteries WHERE abbr = 'TR' AND group_id = '3' )))