I've got a query here that looks for users authorized to a project and it's written in a way that is human readable, however I'm looking to optimize a DB2 query. Is it possible to utilize some nested selects or some clever joining of tables to make this query perform better?
SELECT *
FROM PROJECT p, USER_EMAIL_ACCESS uea, USER_EMAIL e
WHERE (
uea.PROJECT_ID = p.ID and
uea.USER_EMAIL_ID = l.ID and
uea.STATE_ID = 1 and
e.USER_ID = 100 and
e.STATE_ID = 1 and
p.STATE_ID = 1
)
try this :
SELECT *
FROM
PROJECT p
inner join USER_EMAIL_ACCESS uea on (uea.PROJECT_ID, uea.STATE_ID) = (p.ID, p.STATE_ID)
inner join USER_EMAIL e on e.STATE_ID = uea.STATE_ID and e.USER_ID = 100
WHERE p.STATE_ID = 1
Related
I have the following query:
SELECT tours_atp.NAME_T, today_atp.TOUR, today_atp.ID1, odds_atp.K1, today_atp.ID2, odds_atp.K2
FROM (players_atp INNER JOIN (players_atp AS players_atp_1 INNER JOIN (today_atp INNER JOIN odds_atp ON (today_atp.TOUR = odds_atp.ID_T_O) AND (today_atp.ID1 = odds_atp.ID1_O) AND (today_atp.ID2 = odds_atp.ID2_O) AND (today_atp.ROUND = odds_atp.ID_R_O)) ON players_atp_1.ID_P = today_atp.ID2) ON players_atp.ID_P = today_atp.ID1) INNER JOIN tours_atp ON today_atp.TOUR = tours_atp.ID_T
WHERE (((tours_atp.RANK_T) Between 1 And 4) AND ((today_atp.RESULT)="") AND ((players_atp.NAME_P) Not Like "*/*") AND ((players_atp_1.NAME_P) Not Like "*/*") AND ((odds_atp.ID_B_O)=2))
ORDER BY tours_atp.NAME_T;
I'd like to add a field to this query that provides me with the sum of a field in another table (FS) with a few criteria applied.
I've been able to build a stand alone query to get the sum of FS by ID_T as follows:
SELECT tbl_Ts_base_atp.ID_T, Sum(tbl_Ts_mkv_atp.FS) AS SumOfFS
FROM tbl_Ts_base_atp INNER JOIN tbl_Ts_mkv_atp ON tbl_Ts_base_atp.ID_Ts = tbl_Ts_mkv_atp.ID_Ts
WHERE (((tbl_Ts_base_atp.DATE_T)>Date()-2000 And (tbl_Ts_base_atp.DATE_T)<Date()))
GROUP BY tbl_Ts_base_atp.ID_T, tbl_Ts_mkv_atp.ID_Ts;
I now want to match up the sum of FS from the second query to the records of the first query by ID_T. I realise I need to do this using a sub query. I'm confident using these when there's only one table but I consistently get 'syntax errors' when there are joins.
I simplified the first query down to remove all the WHERE conditions so it was easier for me to try and error check but no luck. I guess the resulting SQL will also be easier for you guys to follow:
SELECT today_atp.TOUR, (SELECT Sum(tbl_Ts_mkv_atp.FS)
FROM tbl_Ts_mkv_atp INNER JOIN (tbl_Ts_base_atp INNER JOIN today_atp ON tbl_Ts_base_atp.ID_T = today_atp.TOUR) ON tbl_Ts_mkv_atp.ID_Ts = tbl_Ts_base_atp.ID_Ts AS tt
WHERE tt.DATE_T>Date()-2000 And tt.DATE_T<Date() AND tt.TOUR=today_atp.TOUR
ORDER BY tt.DATE_T) AS SumOfFS
FROM today_atp
Can you spot where I'm going wrong? My hunch is that the issue is in the FROM line of the sub query but I'm not sure. Thanks in advance.
It's difficult to advise an appropriate solution without knowledge of how the database tables relate to one another, but assuming that I've correctly understood what you are looking to achieve, you might wish to try the following solution:
select
tours_atp.name_t,
today_atp.tour,
today_atp.id1,
odds_atp.k1,
today_atp.id2,
odds_atp.k2,
subq.sumoffs
from
(
(
(
(
today_atp inner join odds_atp on
today_atp.tour = odds_atp.id_t_o and
today_atp.id1 = odds_atp.id1_o and
today_atp.id2 = odds_atp.id2_o and
today_atp.round = odds_atp.id_r_o
)
inner join players_atp as players_atp_1 on
players_atp_1.id_p = today_atp.id2
)
inner join players_atp on
players_atp.id_p = today_atp.id1
)
inner join tours_atp on
today_atp.tour = tours_atp.id_t
)
inner join
(
select
tbl_ts_base_atp.id_t,
sum(tbl_ts_mkv_atp.fs) as sumoffs
from
tbl_ts_base_atp inner join tbl_ts_mkv_atp on
tbl_ts_base_atp.id_ts = tbl_ts_mkv_atp.id_ts
where
tbl_ts_base_atp.date_t > date()-2000 and tbl_ts_base_atp.date_t < date()
group by
tbl_ts_base_atp.id_t
) subq on
tours_atp.tour = subq.id_t
where
(tours_atp.rank_t between 1 and 4) and
today_atp.result = "" and
players_atp.name_p not like "*/*" and
players_atp_1.name_p not like "*/*" and
odds_atp.id_b_o = 2
order by
tours_atp.name_t;
I have a slight issue in a SQL Server 2016 (Developer Edition) Database that I am trying to learn on. I have a query that when I run a select, it returns rows fine, but when I try and update on similar column structure it returns 0 rows and I cannot work it out and its driving me crazy :(
The following returns results :
select DISTINCT R.PersonID, R.CompleteDate, E.ExactTime, U.RunCode
FROM Results R
JOIN Run PR ON PR.ID = R.RunID AND PR.ProgrammeID = 8
JOIN Event E ON E.ID = R.CompleteEventID
JOIN Unit U ON U.ID = R.UnitID
JOIN Batches BN ON R.PersonID = BN.ID
But the following updates 0 rows :
UPDATE E
SET ExactTime = BN.CorrectTiming
FROM Event E, Results R, Run PR, Unit U, Batches BN
WHERE R.CompleteEventID = E.ID
AND R.RunID = PR.ID
AND PR.ProgrammeID = 8
AND R.UnitID = U.ID
AND R.PesonID = BN.ID
AND U.RunCode = BN.RunCode
AND R.CompleteDate = BN.CorrectDate
Before I start re-writing again from the ground up, can anyone check my syntax and see if there is anything wrong with that ?
Cheers!
It would be great if you could provide some data sample.
Maybe try this:
UPDATE E
SET E.ExactTime = BN.CorrectTiming
FROM Results R
INNER JOIN Run PR ON PR.ID = R.RunID
AND PR.ProgrammeID = 8
INNER JOIN Event E ON E.ID = R.CompleteEventID
INNER JOIN Unit U ON U.ID = R.UnitID
INNER JOIN Batches BN ON R.PersonID = BN.ID;
I need to improve this query inside a stored procedure, the performance with lots of data broke the application. Is there any way to make it faster?
I need to collect certain columns from several tables to build a dashboard in my app web, others columns I collected in other query and joined in my controller through classes.
EDIT: this query is a part from dynamically transaction, they can change the database.
SELECT
a.fact_num as cotizacion, a.comentario, m.co_cli, k.cli_des,
m.co_ven, l.ven_des, m.fec_emis, m.fec_venc, m.campo8,
a.reng_num, a.co_art, g.art_des, a.co_alma, b.fact_num as pedido,
c.fact_num as factura, d.fact_num as despacho, e.cob_num as cobro,
f.fec_venc as fecha_venc, f.fec_emis as fecha_pedido,
h.odp_num as ord_produccion, h.co_ced as cedula, i.req_num as requisicion,
j.ent_num as cierre
FROM
reng_cac a
LEFT JOIN
cotiz_c m ON a.fact_num = m.fact_num
LEFT JOIN
reng_ped b ON a.co_art = b.co_art AND a.fact_num = b.num_doc AND b.tipo_doc = 'T'
LEFT JOIN
pedidos f ON b.fact_num = f.fact_num
LEFT JOIN
reng_fac c ON b.fact_num = c.num_doc AND a.co_art = c.co_art AND c.tipo_doc = 'P'
LEFT JOIN
reng_ndd d ON c.fact_num = d.num_doc AND a.co_art = d.co_art AND d.tipo_doc = 'F'
LEFT JOIN
reng_cob e ON c.fact_num = e.doc_num AND e.tp_doc_cob = 'FACT'
LEFT JOIN
art g ON a.co_art = g.co_art
LEFT JOIN
spodp h ON b.fact_num = h.doc_ori AND b.co_art = h.co_art
LEFT JOIN
spreqalm i ON h.odp_num = i.odp_num
LEFT JOIN
spcierre j ON h.odp_num = j.odp_num
LEFT JOIN
clientes k ON m.co_cli = k.co_cli
LEFT JOIN
vendedor l ON m.co_ven = l.co_ven
WHERE
a.fact_num BETWEEN '0' AND '999999999'
AND m.fec_emis BETWEEN '01/01/2012' AND '30/06/2012'
AND m.co_cli BETWEEN '' AND 'þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ'
ORDER BY
a.fact_num, a.reng_num ASC
As Nick commented, you always need to run your query in a execution plan. There are some points you need to consider. For instance, having a lot of LEFT JOINs will reduce the performance. Try to see if you can use INNER JOINs where possible. Check if you have proper indexes. If you can attach your execution plan to your question, you will get more helpful answers.
SQL Gurus,
I have a query that uses the "old" style of join syntax as follows using 7 tables (table and column names changed to protect the innocent), as shown below:
SELECT v1_col, p1_col
FROM p1_tbl, p_tbl, p2_tbl, p3_tbl, v1_tbl, v2_tbl, v3_tbl
WHERE p1_code = 1
AND v1_code = 1
AND p1_date >= v1_date
AND p_uid = p1_uid
AND p2_uid = p1_uid AND p2_id = v2_id
AND p3_uid = p1_uid AND p3_id = v3_id
AND v2_uid = v1_uid
AND v3_uid = v1_uid
The query works just fine and produces the results it is supposed to, but as an academic exercise, I tried to rewrite the query using the more standard JOIN syntax, for example, below is one version I tried:
SELECT V1.v1_col, P1.p1_col
FROM p1_tbl P1, v1_tbl V1
JOIN p_tbl P ON ( P.p_uid = P1.p1_uid )
JOIN p2_tbl P2 ON ( P2.p2_uid = P1.p1_uid AND P2.p2_id = V2.v2_id )
JOIN p3_tbl P3 ON ( P3.p3_uid = P1.p1_uid AND P3.p3_id = V3.v3_id )
JOIN v2_tbl V2 ON ( V2.v2_uid = V1.v1_uid )
JOIN v3_tbl V3 ON ( V3.v3_uid = V1.v1_uid )
WHERE P1.p1_code = 1
AND V1.v1_code = 1
AND P1.p1_date >= V1.v1_date
But, no matter how I arrange the JOINs (using MS SQL 2008 R2), I keep running into the error:
The Multi-part identifier "col-name" could not be bound,
where "col-name" varies depending on the order of the JOINs I am attempting...
Does anyone have any good examples on how use the JOIN syntax with this number of tables??
Thanks in advance!
When you use JOIN-syntax you can only access columns from tables in your current join or previous joins. In fact it's easier to write the old syntax, but it's more error-prone, e.g. you can easily forget a join-condition.
This should be what you want.
SELECT v1_col, p1_col
FROM p1_tbl
JOIN v1_tbl ON p1_date >= v1_date
JOIN v2_tbl ON v2_uid = v1_uid
JOIN v3_tbl ON v3_uid = v1_uid
JOIN p_tbl ON p_uid = p1_uid
JOIN p2_tbl ON p2_uid = p1_uid AND p2_id = v2_id
JOIN p3_tbl ON p3_uid = p1_uid AND p3_id = v3_id
WHERE p1_code = 1
AND v1_code = 1
You are not naming the tables in your join such that it doesn't know which column is from which table. Try something like:
SELECT a.v1_col, b.p1_col
FROM p1_tbl b
JOIN p_tbl a ON b.p_uid = a.p1_uid
WHERE b.p1_code = 1
From your query above, I am assuming a naming convention of p2_uid comes from p2_tbl. Below id my best interpretation of WHERE joins to using INNER joins.
SELECT
v1_col, p1_col
FROM
p1_tbl
INNER JOIN p1_tbl
ON p1_tbl.p1_date >= v1_tbl.v1_date
INNER JOIN p_tbl
ON p_tbl.p_uid = p1_tbl.p1_uid
INNER JOIN p2_tbl
ON p2_tbl.p2_uid = p1_tbl.p1_uid
INNER JOIN v2_tbl
ON p2_tbl.p2_id = v2_tbl.v2_id
INNER JOIN p3_tbl
ON p3_tbl.p3_uid = p1_tbl.p1_uid
INNER JOIN v3_tbl
ON p3_tbl.p3_id = v3_tbl.v3_id
INNER JOIN v1_tbl
ON v1_tbl.v1_uid = v2_tbl.v2_uid
AND v1_tbl.v1_uid = v3_tbl.v2_uid
WHERE
p1_code = 1
AND
v1_code = 1
Some general points I have found useful in SQL statements with many joins.
Always fully qualify the names. I.e dont use ID , rahter use
TableName.ID
Dont use aliases unless there is meaning. (I.e. joining a table to
its self where aliasing is needed.)
My SQL Query below is now Returning the RoomsAvailable field correctly except when theres 0 rooms taken, in which the SQL command subtracts number_of_rooms with NULL and outputs NULL to the Column. I have tried numerous ISNULL variations and found that it doesnt work; anyone know how I should be doing this?
SQL :
SELECT
Hotel_2.hotel_code,
Hotel_2.hotel_country,
Room_type_rates_2.room_type_code,
Room_type_rates_2.number_of_rooms,
Types_2.room_type,
Room_type_rates_2.rates,
Room_type_rates_2.number_of_rooms -
(SELECT
DISTINCT (SELECT
COUNT(dbo.Hotel.hotel_code) AS RoomsTake
FROM
dbo.Hotel
INNER JOIN dbo.Hotel_Reservation
ON dbo.Hotel.hotel_code = dbo.Hotel_Reservation.hotel_code
INNER JOIN dbo.Room_type_rates
ON dbo.Hotel.hotel_code = dbo.Room_type_rates.hotel_code
INNER JOIN dbo.Types
ON dbo.Hotel_Reservation.room_type_code = dbo.Types.room_type_code
AND dbo.Room_type_rates.room_type_code = dbo.Types.room_type_code
WHERE
(dbo.Room_type_rates.room_type_code = Room_type_rates_1.room_type_code)
AND (dbo.Hotel.hotel_code = Hotel_1.hotel_code)
AND (dbo.Hotel_Reservation.checkin_date >= Hotel_Reservation_1.checkin_date)
AND (dbo.Hotel_Reservation.checkout_date <= Hotel_Reservation_1.checkout_date)
) AS RoomsTaken
FROM
dbo.Hotel AS Hotel_1
INNER JOIN dbo.Hotel_Reservation AS Hotel_Reservation_1
ON Hotel_1.hotel_code = Hotel_Reservation_1.hotel_code
INNER JOIN dbo.Room_type_rates AS Room_type_rates_1
ON Hotel_1.hotel_code = Room_type_rates_1.hotel_code
INNER JOIN dbo.Types AS Types_1
ON Hotel_Reservation_1.room_type_code = Types_1.room_type_code
AND Room_type_rates_1.room_type_code = Types_1.room_type_code
WHERE
(Hotel_Reservation_1.checkin_date >= '11/19/2011')
AND (Hotel_Reservation_1.checkout_date <= '12/01/2011')
AND (Hotel_1.hotel_country = 'Adelaide')
AND (Types_1.room_type_code = Types_2.room_type_code)
) AS RoomsAvailable
FROM
dbo.Hotel AS Hotel_2
INNER JOIN dbo.Room_type_rates AS Room_type_rates_2
ON Hotel_2.hotel_code = Room_type_rates_2.hotel_code
INNER JOIN dbo.Types AS Types_2
ON Room_type_rates_2.room_type_code = Types_2.room_type_code
Current Output :
ADL20 Adelaide CPL 6 Couple Suite 514.0000 3
ADL20 Adelaide FYU 3 Family Suite 533.0000 2
ADL20 Adelaide KNG 2 King's Bedroom 556.0000 NULL
Do you mean this?:
...ISNULL(COUNT(dbo.Hotel.*),0)...
Or is the problem that you're getting NULL at all? In that case I would suspect your JOINs may have a problem.
You can wrap an ISNULL around any nested subquery or value.