SQL SHOW one more column name FROM operator in - sql

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' )))

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;

How To use Where instead of Group by?

I wrote a query , that gives me this Output :
(This is Just a sample obviously the Output Table contains 300000 rows approximatly)
And This is my Query :
proc sql;
create Table Output as
select ID_User, Division_ID, sum(conta) as Tot_Items, max(Counts) as Max_Item
from (select c.ID_User , c.Div_ID as Division_ID, ro.code as Mat, count(*) as Counts
from Ods.R_Ordini o
inner join DMC.Cust_Dupl c
on User_ID = ID_User
inner join ods.R_Nlines ro
on ro.Orders_Id = o.Id_Orders AND RO.SERVICE = 0
inner join ods.R_Mat m
on ro.Mat_Id = Id_Mat and flag = 0
group by
ID_User,
C.Division_ID,
Ro.Code
Having Counts > 1
)
group by
Id_User,
Division_ID
Order by
Tot_Item DESC
;
quit;
So , What i want is to re-write this Query , but instead of the Group by i want to use the Where Condition , (WHERE=(DIVISION_ID=3)) this is the condition.
I tried several attempts , with some i got errors , and with others i did got an output , but the output was not like the original one.
any help would be much appreciated , thank you.
The SAS data set option (where=(<where-expression>)) can only be coded adjacent to a data set name. So the option would have to be applied to the data set containing the column div_id that is the basis for computed column division_id. That would be table alias c
DMC.Cust_Dupl(where=(div_id=3)) as c
Or just use a normal SQL where clause
…
)
where division_id=3
group by …
Just use WHERE DIVISION_ID=3 before group by.
select ID_User, Division_ID, sum(conta) as Tot_Items, max(Counts) as Max_Item from (select c.ID_User , c.Div_ID as Division_ID, ro.code as Mat, count(*) as Counts from Ods.R_Ordini o inner join DMC.Cust_Dupl c on User_ID = ID_User inner join ods.R_Nlines ro on ro.Orders_Id = o.Id_Orders AND RO.SERVICE = 0 inner join ods.R_Mat m on ro.Mat_Id = Id_Mat and flag = 0 WHERE DIVISION_ID=3 group by ID_User, C.Division_ID, Ro.Code Having Counts > 1 ) group by Id_User, Division_ID Order by Tot_Item DESC

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).

Get Distinct values from one table in a join query containing column data type like ntext

I have two tables
Review and ProjectsReview. I want to change the order by columns without impacting the result. Initial order by was on createdDate column from review table.
Initial query is as below.
SELECT
*
FROM Review r
WHERE (status IS NULL
OR fstatus = '')
AND (crBy = '100'
OR crByPr = '')
ORDER BY createdDate
The query returns 8 rows.
The user wants to change the order by using program name which is in another table. The query to get the same is as below.
SELECT
r.*
FROM Review r
INNER JOIN ProjectsReview rp
ON rp.rID = r.rID
WHERE (status IS NULL
OR fstatus = '')
AND (crBy = '100'
OR crByPr = '')
ORDER BY prNo, prName
This returns 10 rows. But the required result is only 8 rows and only columns of review table.
I cannot apply group by on all the columns from Review table since there are data types with image and ntext.
Is there a way to achieve this without inserting the data to a temp table and get distinct values.
Try this
with cte
as
(
select
rn = row_number() over(partition by rID order by prNo,prName),
rID,
prNo,
prName
from ProjectsReview
)
SELECT r.*
FROM Review r
inner join cte rp on rp.rID =r.rID
WHERE (status IS NULL OR fstatus = '') AND (crBy = '100' OR crByPr = '')
and cte.rn = 1
ORDER BY prNo,prName

selecting in 4 tables with conditions

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.