sql query help multi joins? - sql

here are my tables, im using sql developer oracle
Carowner(Carowner id, carowner-name,)
Car (Carid, car-name, carowner-id*)
Driver(driver_licenceno, driver-name)
Race(Race no, race-name, prize-money, race-date)
RaceEntry(Race no*, Car id*, Driver_licenceno*, finishing_position)
im trying to list to do the query below
which drivers have come second in races from the start of this year.
lncluding race name, driver name, and the name of the car in the output
i have attempted
select r.racename, d.driver-name, c.carowner-name
from race r, driver d, car c, raceentry re
where re.finishing_position = 2 and r.race-date is ...

Something like:
select r.racename, d.driver-name, c.carowner-name
from race r
join raceentry re on r.race_no = re.race_no
join car c on re.car_Id = c.car_id
join driver d on re.driverliscenceNo = d.driverliscenceNo
where re.finishing_position = 2 and r.race-date >='20130101'
This assumes only one car and one driver with a finsih place of 2nd in a particular race. You may need more conditions otherwise. If this is your own table design, you need to start right now learning to be consistent in your nameing between tables. It is important. Fields that are in multiple tables should have the same name and data type. Also you need to stop using implicit syntax. This ia aSQL antipattern and a very poor programming technique. It leads to mistakes such as accidental cross joins and is harder to read and maintain when things get more complex. As you are clearly learning, you need to stop this bad habit right now.

First off, multiple joins in the where clause are hard to get used to when you define more than 3 or 4 tables IMHO.
Do this instead:
Select
a.columnfroma
, b.columnfromb
, c.columnfromc
from tablea a
join tableb b on a.columnAandBShare = b.columnAandBShare
join tablec c on b.columnBandCShare = c.columnBandCShare
This while no one would say is a method you have to use, it is a much more readable method of performing joins.
Otherwise you are doing the joins in the where clause and if you have other predicates with your joins you are going to have to comment out which is which if you ever need to go back and look at it.

Related

Oracle non Ansi to Ansi T-SQL

I am a SQL server guy, with limited Oracle coding. I have inherited a bunch of views that I need to convert to ANSI. What I am looking for is someone to educate me, if possible, on a systematic way to do this in steps. I have junior guys that would read and understand TSQL style code, instead of the way it is. I want to take this knowledge, and have them start working on them; there are many. A conversion tool will not work, we don't have time to play with one, no budget to buy it, and our IT department will not let us install anything. (We have to do this manually)
I would like to know the steps (systematic approach) based on interpreting the code, not learn the data or try to understand why the existing code was written the way it was.
For example, are these the steps:
Reorder the tables to match how they are in the where clause.
Separate the lines in the where clause based on their table, so that it is easier to read.
Replace the Oracle join operators with left, right, outer, etc.
Leave the lines with defined values in the where clause, or should I include them with an "AND" in the table join.
This task will be done by junior SQL server guys, so it has to be as simple and straight forward as possible.
FROM WORK MECHANISMS WM,
WT_MANPOWER_RESOURCES WTMR,
LOGICAL_ITEMS LI,
APSWHS.WMX_LOG_REL_ELEM WLRE,
WMECH_DSGN_COMP_ELEMENTS WDCE,
WORK_TASKS WT,
persons_v per,
APSWHS.WMX_WO_WF_STATUS WFA,
RT_DETAILS RTD
WHERE
WFA.WF_SEQ > 639
AND WTMR.WTASK_WMECH_DB_ID = WM.DB_ID
AND WTMR.WTASK_DB_ID = 0
AND WTMR.WTMANPOW_TYPE = ‘LEAD’
AND WT.WMECH_DB_ID = WM.DB_ID
AND WT. DB_ID= 0
AND WFA.WM_DB_ID = WM.DB_ID
AND PER.per_db_id = wm.assigned_to_per_db_id
AND RTD.WMECH_DB_ID = WM.DB_ID
AND WDCE .WMECH_DB_ID = WFA.WM_DB_ID
AND WDCE.LITM_ID = WLRE.LITM_ID
AND WDCE.LITM_ID = LI.ID
AND WDCE.PRIMARY_DCID_FLAG = ‘Y’
I'm assuming that you want to migrate from table lists (join predicates in WHERE clause) to ANSI JOIN syntax. This has nothing to do with T-SQL.
Ideally, you'll take an ERD and check in what order the tables should be listed, visually. I personally find that easier than from mere text. Although, it is possible to do with plain text as well. Here are the steps:
Take the first table and all its non-join predicates:
FROM WORK_MECHANISMS WM
WHERE 1 = 1 -- No predicates on this table
Take the next table that you can join to the first one, and all of its join and non-join predicates
FROM WORK_MECHANISMS WM
JOIN WT_MANPOWER_RESOURCES WTMR
ON WTMR.WTASK_WMECH_DB_ID = WM.DB_ID
WHERE WTMR.WTASK_DB_ID = 0
AND WTRM.WTMANPOW_TYPE = 'LEAD'
And the next table...
Observe that this isn't the next table in your original table list, but another one, i.e. the next one that can be joined to the existing join graph without creating a cartesian product. In particular, I skipped (for now) LOGICAL_ITEMS and APSWHS.WMX_LOG_REL_ELEM and WMECH_DSGN_COMP_ELEMENTS. I will add them to the graph later.
FROM WORK_MECHANISMS WM
JOIN WT_MANPOWER_RESOURCES WTMR
ON WTMR.WTASK_WMECH_DB_ID = WM.DB_ID
JOIN WORK_TASKS WT
ON WT.WMECH_DB_ID = WM.DB_ID
WHERE WTMR.WTASK_DB_ID = 0
AND WTRM.WTMANPOW_TYPE = 'LEAD'
AND WT.DB_ID = 0
And the next table...
You continue adding tables to your new statement, until you've added all tables. If you ever encounter a (+) operator, "just" get the LEFT JOIN semantics right.

Converting subquery to join assistance

I am my subquery is severely slowing my full query down in MySQL. I'm in the process of converting the original query to work on MySQL as I'm moving away from SQL Server where it has worked wonderfully. MySQL on the other hand isnt too happy. Was wondering if anyone could assist in helping me with a conversion solution to a join as I'm not well versed in joins quite yet. Thanks!
select a.crm_ticket_details_detail,
crm_ticket_created_date,
crm_ticket_id,
crm_ticket_customer_id,
c.crm_assigned_user
from php_crm.crm_ticket,
php_crm.crm_ticket_details a,
php_crm.crm_assigned c
where crm_ticket_resolved_date is null
and crm_ticket_id = a.crm_ticket_details_ticket_id
and a.crm_ticket_details_type = 'issue'
and c.crm_assigned_ticket_id = crm_ticket_id
and c.crm_assigned_id = (select max(d.crm_assigned_id)
from php_crm.crm_assigned d
where d.crm_assigned_ticket_id = crm_ticket_id)
SELECT
details.crm_ticket_details_detail,
CT.crm_ticket_created_date,
CT.crm_ticket_id,
CT.crm_ticket_customer_id,
ASSIGNED.crm_assigned_user
FROM
php_crm.crm_ticket CT (NONAME)
INNER JOIN php_crm.crm_ticket_details DETAILS -- (A)
ON CT.crm_ticket_id = DETAILS.crm_ticket_details_ticket_id
INNER JOIN php_crm.crm_assigned ASSIGNED -- (C)
ON CT.crm_ticket_id = ASSIGNED.crm_assigned_ticket_id
WHERE
crm_ticket_resolved_date IS NULL
AND DETAILS.crm_ticket_details_type = 'issue'
AND
AND ASSIGNED.crm_assigned_id = (SELECT
max(d.crm_assigned_id)
FROM
php_crm.crm_assigned d
WHERE
d.crm_assigned_ticket_id = crm_ticket_id)
I believe that's what you're looking for. I can't speak to whether it will actually improve performance, although it will certainly make it easier to understand. I'm not sure the old style of joins is actually less efficient; just harder to read / easier to make product joins with.
That said, if there are other common keys between the three tables that are being indirectly neutralized in other parts of the logic then that could have a performance impact.
(EDIT: Actually not sure if this was what you're looking for, reread your question and you seem focused on the subquery... I don't see any problems jumping out with that, would need more details to address that.)

Produce a Query viewing multiple tables

I have been given a database, the structure and data values are all unchangable and have been provided with a question.
Produce a query to list the holiday code, holiday description, holiday duration and site description for all holidays which visit site code 101. Your answer must not assume that site code 101 will always have the same site description.
I am confused on how to tackle this question. I have tried Multiple joins, different dot notation and googled the question to hell and back. Any help?
Table 1 - Holiday_Details
Holiday_Code - Country_Visited - Holiday_Duration - Holiday_Desc - Rating_Code - Cost
Table 2 - Site_Of_Holiday
Site_Description - Site_Code
Table 3 - Site_Visited
Holiday_Code - Site_Code
Comments have asked for previous attempts. This was my first.
SELECT holiday_code,
holiday_desc,
holiday_duration site_of_holiday.Site_Name
FROM holiday_details
JOIN site_visited
ON holiday_code = site_visited.holiday_code
JOIN site_of_holiday
ON site_visited.site_code = site_of_holiday.site_code
WHERE site_of_holiday.site_code = 101;
For future reference, you'll get a better response if you post a lot more detail about your failed attempts. By that, I mean code. Using SO to solve your homework assignments is frowned upon but, like a commenter said, once you've wracked your brain we're willing to help.
You seem like you may have actually tried real hard, so I'll throw you a bone...
The trick to navigating multiple tables is to find the "pairs" of matching columns. In this case you want to find a path between the tables Site_Of_Holiday (which has Site_Description) and Holiday_Details (which has everything else).
The columns that match between each pair of tables are:
Holiday_Code is found in both Site_Visited and Holiday_Details
Site_Code is found in both Site_Of_Holiday and Site_Visited
This allows you to build a path between the tables that contain all of the columns we want in the output. You would do this, in this case, using INNER JOINs across those matching column pairs.
Once you've joined the tables, think of the result like a giant table whose columns include all columns from all three tables (prefixed with whatever you 'name' the table during the joins). Now you just filter on the Site_Code with the usual WHERE clause.
Here's the full example - let me know if it works for you:
SELECT hd.Holiday_Code, hd.Holiday_Desc, hd.Holiday_Duration, soh.Site_Description
FROM Holiday_Details hd
INNER JOIN Site_Visited sv ON hd.Holiday_Code = sv.Holiday_Code
INNER JOIN Site_Of_Holiday soh ON sv.Site_Code = soh.Site_Code
WHERE sv.Site_Code = 101
Good luck!
P.S. In case any Americans get a similar assignment, here's the translation ;-)
SELECT vd.Vacation_Code, vd.Vacation_Desc, vd.Vacation_Duration, sov.Site_Description
FROM Vacation_Details vd
INNER JOIN Site_Visited sv ON vd.Vacation_Code = sv.Vacation_Code
INNER JOIN Site_Of_Vacation sov ON sv.Site_Code = sov.Site_Code
WHERE sv.Site_Code = 101

relationships produce duplicate records on query, DISTINCT does not work, any other solutions available?

I am new to this portal. I have a very simple problem to be solved. It is related to the ANSI SQL. I am writing a reports using BIRT and I am fetching the data from several tables. I understand how the SQL joins work but maybe not fully. I researched google for hours and I could not find relevant answer.
My problem is that one of the relationships in the code produce a duplicate result (the same row is copied - duplicated). I was so determined to solve it I used every type of join available. Some of this SQL was produced already. I shall post my code below. I know that one of the solutions to my problem is use of the 'DISTINCT' keyword. I have used it and it does not solve my problem.
Can anyone propose any solution to that?
Sample code:
SELECT DISTINCT
partmaster.partdesc,
partmaster.uom,
traders.name AS tradername,
worksorders.id AS worksorderno,
worksorders.partid,
worksorders.quantity,
worksorders.duedate,
worksorders.traderid,
worksorders.orderid,
routingoperations.partid,
routingoperations.methodid,
routingoperations.operationnumber,
routingoperations.workcentreid,
routingoperations.settime,
routingoperations.runtime,
routingoperations.perquantity,
routingoperations.description,
routingoperations.alternativeoperation,
routingoperations.alternativeoperationpreference,
machines.macdesc,
machines.msection,
allpartmaster.partnum,
allpartmaster.nbq,
allpartmaster.partdesc,
routingoperationtools.toolid,
tools.tooldesc,
CAST (emediadetails.data as VARCHAR(MAX)) AS cplandata
FROM worksorders
INNER JOIN partmaster ON worksorders.partid = partmaster.partnum
INNER JOIN traders traders ON worksorders.traderid = traders.id
INNER JOIN routingoperations routingoperations ON worksorders.partid = routingoperations.partid
AND worksorders.routingmethod = routingoperations.methodid
INNER JOIN allpartmaster allpartmaster ON routingoperations.partid = allpartmaster.partnum
LEFT OUTER JOIN machines machines ON routingoperations.workcentreid = machines.macid
LEFT OUTER JOIN routingoperationtools routingoperationtools ON routingoperationtools.partid = routingoperations.partid
AND routingoperationtools.routingmethod = routingoperations.methodid
AND routingoperationtools.operationnumber = routingoperations.operationnumber
LEFT OUTER JOIN tools tools ON tools.toolid = routingoperationtools.toolid
LEFT OUTER JOIN emediadetails ON emediadetails.keyvalue1 = worksorders.id
AND emediadetails.keyvalue2 = routingoperations.operationnumber
AND emediadetails.emediaid = 'worksorderoperation'
I do not have too much of the test data but I know that one row is copied twice as the result of the query below even tho I used DISTINCT keyword. I know that my problem is rather specific and not general but the solution that someone will propose may help others with the similar problem.
I can't solve your problem for you without some test data, but I have some helpful hints.
In principle, you should be really careful with DISTINCT - its a great way of hiding bugs in your query. Only use DISTINCT if you are confident that the underlying data contains legitimate duplicates. If your joins are wrong, and you're getting a cartesian product, you can remove the duplicates from the results with DISTINCT - but that doesn't stop the cartesian product being generated. You'll get very poor performance, and possibly incorrect data.
Secondly, I am pretty sure that DISTINCT works properly - you are almost certainly not getting duplicates, but it may be hard to spot the difference between two rows. Leading or trailing spaces in text columns, for instance could be to blame.
Finally, to work through this problem, I'd recommend building the query up join by join, and seeing where you get the duplicate - that's the join that's to blame.
So, start with:
SELECT
traders.name AS tradername,
worksorders.id AS worksorderno,
worksorders.partid,
worksorders.quantity,
worksorders.duedate,
worksorders.traderid,
worksorders.orderid
FROM worksorders
INNER JOIN traders traders ON
worksorders.traderid = traders.id
and build up to the next join.
Are you sure the results are exact duplicates? Makes sure there isn't one column that actually has a different value.

MySQL is returning an "column ambiguous" error when it used to work before I upgraded

I recently upgraded MySQL to 5.1.41. Before the upgrade the following SQL worked (or at least I thought I remembered it working...it has been a few weeks since designing this...). Now the SQL gives me an error stating that the "archived" column is ambiguous. How can I write this differently, or is there a different problem I'm not aware of?
I simply want to return the "unit_id", "lease_count" (stored in another table with a unit_id that should correspond with the "a.unit_id"), and "lease_archived_count (stored in another table with a unit_id that should correspond with the "a.unit_id").
SELECT a.unit_id,
(SELECT count(*) FROM o_leases WHERE unit_id = a.unit_id AND archived = 0) as lease_count,
(SELECT count(*) FROM o_leases WHERE unit_id = a.unit_id AND archived = 1) as lease_archive_count
FROM p_unit a, properties b, portfolio c
WHERE a.property_id = b.properties_id
AND b.portfolio_id = c.portfolio_id
AND a.archived = 0
Thanks for your help.
There can only be one place where this error is referring to. I suggest to give the tables in the sub select also an alias:
(SELECT count(*) FROM o_leases o WHERE o.unit_id = a.unit_id AND o.archived = 0) as lease_count,
(SELECT count(*) FROM o_leases o WHERE o.unit_id = a.unit_id AND o.archived = 1) as lease_archive_count
It seems that it collides with the archived field of p_unit.
I would guess the error is because o_leases is not the only table that has an archived field. p_unit Or properties or portfolio must have that column as well.
However you have several other things that should also be fixed. First in most databases correlated subqueries are poor performers and should be rewritten as joins (although in this case you probably only need a case statement and a join). You should notgenerally even consider writing correlated subqueries.
Second, you should NEVER use implicit joins. Extremely bad idea that leads to poor maintainability and accidental cross joins as well as a generally poor understanding of joins. Bad bad bad. This kind of code was replaced 18 years ago, would you still be using C# or Java code relaced witha better method even five years ago?