MySQL Inner Join should not produce results ... but it does - mysql

I've come across a situation where an incorrect query was generated:
select a.id, e.ethnicity_cd, e.appl_person_id from applicants a
inner join ucpsom_production_ucpsom_production.ETHNICITY e
on e.appl_person_id = a.id
where a.amc_id = 12977319
The error is in the join statement. The statement should read "e.appl_person_id = a.appl_person_id" and return no records because there is no e.appl_person_id value equal to "80cbacb2-8444-11df-acd2-12313b079cc4", the a.id value.
What is happening then is that MySQL is matching values of 80 (for e.appl_person_id) to values of "80cbacb2-8444-11df-acd2-12313b079cc4" (for a.id). Thus:
80 = "80cbacb2-8444-11df-acd2-12313b079cc4".
*Note: e.app_person_id is a decimal and a.id is a string.* It looks like MySQl is comparing the first two characters of the a.id value to the e.appl_person_id value.
Can anyone explain why this is happening with MySQL, and also, is this MySQL specific in nature?
Thanks much.

Looks like MySQL is attempting to do an implicit conversion of data types (from string to int in this case).
Most databases will do some conversions implicitly, for example SQL server will implicitly convert from smallint to int, but which conversions are done implicitly would be DBMS specific.

Related

MySQL select unreaded messages

So i'm trying to select unread messages with a query, but the results are blank. I need to get the info from a seperate table read so it will know it was read or not. Im trying to do something like a IF statement so if readed not exists it will be unread, but i can't get it fixed
this is my query:
SELECT * FROM notify
INNER JOIN readed ON readed.acc_ID = '26' AND readed.user_ID = '6'
AND readed.msg_ID = notify.ID AND readed.readed != '1' OR readed.ID IS NULL
WHERE notify.groep = '1'
DB - readed
ID - int
user_ID - int
acc_ID - int
msg_ID - int
readed - enum ('0','1')
DB - notify
ID - int
notfi - text
thumb_src - text
title - text
url - text
groep - int
I hope someone know whats the problem!
The query seems correct to me, except the part with the OR, so I suppose that the problem is with the data. I will first try to show how you could improve the query nevertheless, and then try to show how to debug your data.
First, let's leave away the OR condition since this won't work as expected in a JOIN ON clause.
Second, when comparing integer fields to values, you should not put quotes around the values. This will only worry every person who tries to understand the query because the quotes denote string values, and it will worry (i.e. slow down) MySQL's parser, because it must convert the string values to numbers.
Third, mixing up normal WHERE conditions and JOIN ON conditions is worrying and bad style (IMHO). I always recommend to put only the conditions which actually link the tables into the JOIN ON clause, and other conditions elsewhere.
Following this advice would lead to something like that:
SELECT * FROM
notify INNER JOIN readed ON
readed.msg_ID = notify.ID
WHERE
readed.acc_ID = 26 AND
readed.user_ID = 6 AND
readed.readed != '1' AND
notify.groep = 1
This should do the same as your original query minus the OR part.
Now, since we suspect that there is a problem with the data, we can begin to debug the data. First, leave away the WHERE clause:
SELECT * FROM
notify INNER JOIN readed ON
readed.msg_ID = notify.ID
If this returns data, then you at least know that there are rows in the readed table matching rows in the notify table. If it does not return any data, then there are no rows which fit together, and have found the root of your problem.
Provided that the above returns data, re-add the WHERE clause line by line and test after each step. For example, start with
SELECT * FROM
notify INNER JOIN readed ON
readed.msg_ID = notify.ID
WHERE
readed.acc_ID = 26 AND
and continue with
SELECT * FROM
notify INNER JOIN readed ON
readed.msg_ID = notify.ID
WHERE
readed.acc_ID = 26 AND
readed.user_ID = 6 AND
and so on, testing the query each time.
That way, you hopefully will find out where the problem is. I am convinced that the problem is with the data, not with the query.

Inner join on a partial column in Access

I'm attempting to join two tables in MS Access 2010 where the join condition is part of(A.col1) = B.col2. I've not been able to figure out how to do this so far.
My two tables have these critical columns:
Table 1 has column ICD9 Code-Description* with values like:842.00 - Sprain/strain, wrist924.11 - Contusion, knee
Table 2 has column Dx with values like:842924.11
I have tried these two join criteria:
FROM Table1
INNER JOIN Table2 ON Table1.Replace(LTrim(Replace(Left(ICD9Code-Description],
(InStr(1,[ICD9Code-Description]," "))-1),"0"," "))," ","0")
= Table2.Dx
and
SELECT ICD9
FROM Table2 INNER JOIN
(SELECT Replace(LTrim(Replace(Left([ICD9 Code-Description],
(InStr(1,[ICD9 Code-Description]," "))-1),"0"," "))," ","0") AS ICD9
FROM Table1)
ON Diag.DX = ICD9
Neither of which Access likes.
I'd like to avoid pulling out the join criteria portion into its own column in Table1 if at all possible.
What would be the Access way of doing this?
*Don't hate me for the column name. I didn't create it, I just have to support it.
The Val() function "Returns the numbers contained in a string as a numeric value of appropriate type." (See the Val Function help topic in Access' built-in help system.)
The "neat thing" for your situation is it reads characters from the string until it encounters a character which can't be part of a valid number. But then it doesn't throw an error. It just keeps the numeric characters it's already collected and ignores the rest.
Here's two of your examples in the Immediate window ...
? Val("842.00 - Sprain/strain, wrist")
842
? Val("924.11 - Contusion, knee")
924.11
So Val() should make your JOIN much simpler, even though you would need to also apply it on the Table2.Dx strings ...
FROM
Table1 INNER JOIN Table2
ON Val(Table1.[ICD9Code-Description]) = Val(Table2.Dx)

Join Tables with sum in sql query

It is showing Sum(with table name) is not valid. Kindly help:
Modws.DisplayDataGrid(dgvClosingBalance,
"Select
Invoice.Customer, Invoice.Sum(Total),
RptTempTable.Sum(INVOICETOTAL), RptTempTable.Sum(CNTOTAL),
RptTempTable.Sum(DEBITTOTAL), RptTempTable.Sum(RECEIPTTOTAL)
From Invoice
inner join RptTempTable on Invoice.Customer = RptTempTable.Customer")
RptTempTable.Sum(INVOICETOTAL) should be Sum(RptTempTable.INVOICETOTAL)
The same goes for the other calls to sum()
The table prefix belongs to the column name not the function call.
MySQL will accept this invalid SQL and will return "inderminate" (aka "random") values instead.
To understand the implications of MySQL's "loose" (aka "sloppy") group by implementation you might want to read these articles:
http://www.mysqlperformanceblog.com/2006/09/06/wrong-group-by-makes-your-queries-fragile/
http://rpbouman.blogspot.de/2007/05/debunking-group-by-myths.html

MySQL: Subquery returns more than 1 row

I know this has been asked plenty times before, but I cant find an answer that is close to mine.
I have the following query:
SELECT c.cases_ID, c.cases_status, c.cases_title, ci.custinfo_FName, ci.custinfo_LName, c.cases_timestamp, o.organisation_name
FROM db_cases c, db_custinfo ci, db_organisation o
WHERE c.userInfo_ID = ci.userinfo_ID AND c.cases_status = '2'
AND organisation_name = (
SELECT organisation_name
FROM db_sites s, db_cases c
WHERE organisation_ID = '111'
)
AND s.sites_site_ID = c.sites_site_ID)
What I am trying to do is is get the cases, where the sites_site_ID which is defined in the cases, also appears in the db_sites sites table alongside its organisation_ID which I want to filter by as defined by "organisation_ID = '111'" but I am getting the response from MySQL as stated in the question.
I hope this makes sense, and I would appreciate any help on this one.
Thanks.
As the error states your subquery returns more then one row which it cannot do in this situation. If this is not expect results you really should investigate why this occurs. But if you know this will happen and want only the first result use LIMIT 1 to limit the results to one row.
SELECT organisation_name
FROM db_sites s, db_cases c
WHERE organisation_ID = '111'
LIMIT 1
Well the problem is, obviously, that your subquery returns more than one row which is invalid when using it as a scalar subquery such as with the = operator in the WHERE clause.
Instead you could do an inner join on the subquery which would filter your results to only rows that matched the ON clause. This will get you all rows that match, even if there is more than one returned in the subquery.
UPDATE:
You're likely getting more than one row from your subquery because you're doing a cross join on the db_sites and db_cases table. You're using the old-style join syntax and then not qualifying any predicate to join the tables on in the WHERE clause. Using this old style of joining tables is not recommended for this very reason. It would be better if you explicitly stated what kind of join it was and how the tables should be joined.
Good pages on joins:
http://dev.mysql.com/doc/refman/5.0/en/join.html (for the right syntax)
http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html (for the differences between the types of joins)
I was battling this for an hour, and overcomplicated it completely. Sometimes a quick break and writing it out on an online forum can solve it for you ;)
Here is the query as it should be.
SELECT c.cases_ID, c.cases_status, c.cases_title, ci.custinfo_FName, ci.custinfo_LName, c.cases_timestamp, c.sites_site_ID
FROM db_cases c, db_custinfo ci, db_sites s
WHERE c.userInfo_ID = ci.userinfo_ID AND c.cases_status = '2' AND (s.organisation_ID = '111' AND s.sites_site_ID = c.sites_site_ID)
Let me re-write what you have post:
SELECT
c.cases_ID, c.cases_status, c.cases_title, ci.custinfo_FName, ci.custinfo_LName,
c.cases_timestamp, c.sites_site_ID
FROM
db_cases c
JOIN
db_custinfo ci ON c.userInfo_ID = ci.userinfo_ID and c.cases_status = '2'
JOIN
db_sites s ON s.sites_site_ID = c.sites_site_ID and s.organization_ID = 111

Multiple joins involving same table produces "column doesn't exist" error - MySQL

I'm new to joins and I'm sure this is ridiculously simple. If I remove one join in the query the remainder of the query works regardless of which join I remove. But as shown it gives the error saying the column doesn't exist. Any pointers?
select
loc_carr.address1 as carr_addr1,
loc_cust.address1 as cust_addr1
from db_name.carrier, db_name.customer
join db_name.location as loc_carr on vats.carrier.location_id=loc_carr.location_id
join db_name.location as loc_cust on vats.customer.location_id=loc_cust.location_id
thanks
I'll take a guess that there is a column named something like carrier_id that can be used to join the carrier and customer tables. Given that assumption, try this:
select
loc_carr.address1 as carr_addr1
, loc_cust.address1 as cust_addr1
from vats.carrier as a
join vats.customer as b
on b.carrier_id=a.carrier_id
join vats.location as loc_carr
on loc_carr.location_id=a.location_id
join vats.location as loc_cust
on loc_cust.location_id=b.location_id
Notice the use of aliases for the table references to make things easier to read. Also note how I'm using explicit SQL join syntax (instead of listing tables separated by commas).
#Bob Duell has the solution for your problem. To understand better why this error is produced, notice that in the FROM clause, you "join" tables using both explicit JOIN syntax and the implicit joins with comma: , which is (almost) equivalent to a CROSS JOIN. The precedence however of JOIN is stronger than the comma , operator. So, that part is parsed like this:
FROM
( db_name.carrier )
,
( ( db_name.customer
JOIN db_name.location AS loc_carr
ON carrier.location_id = loc_carr.location_id -- this line
) -- gives the error
JOIN join db_name.location AS loc_cust
ON customer.location_id = loc_cust.location_id
)
In the mentioned line above, the vats.carrier.location_id throws the error, as there is no carrier table in that scope (inside that parenthesis).