I just learned how to use JOINS (so please be gentle ;) ), and wrote this query:
SELECT 1
FROM `T1`
INNER JOIN `T2` ON `T1`.`T1_ID` = `T2`.`REQUIREMENT`
WHERE `T2`.`T1_ID` = XXX
AND `T1`.`STATEMENT` = YYY
AND `T2`.`REQUIREMENT` != 0 //last row does not work as intended!
It works perfectly without the last condition: if T1_ID from T1 does match REQUIREMENT from T2 for given T1_ID (XXX) - it does work. I wanted additional STATEMENT from T1 to be match (YYY) - and it still does work.
But then I realized, that I need to exclude one cause: when T2.REQUIREMENT is equal to 0, I want this query to return 1 regardless of the JOIN formula. The problem is, that if T2.REQUIREMENT = 0, I know for sure that there will not be any T1.T1_ID entry that will match the JOIN requirements. So I understand, that this last condition has no right to work like I'd wish it was.
What I need is some kind of IF statement. Something that would work like:
SELECT 1
IF (`T2`.`REQUIREMENT`!=0) //if true, don't even go to join, and return 1
OR (my previous join query)
The thing is, that I have no idea how to implement such IF statement into mysql.
Any ideas? Thanks.
Sample data:
T1:
id STATEMENT T1_ID
1 irrelevant 1
2 irrelevant 5
T2:
id T1_ID REQUIREMENT
1 1 0
2 2 0
3 3 1
4 4 3
5 5 4
6 6 5
7 7 6
Such setup should return 1 for T1_ID equal 1, 2, 3, 6.
In addition, if it's even possible in single query, I'd like it to return 1 as well even if T1 was empty, for all T2.REQUIREMENT=0 - in this case T1_ID equal 1, 2.
Just FYI, good start on your post and example... tableName.columnName references (or alias.columnName) should always be provided to prevent ambiguity that others don't know your table structure. Also, you only really need the tick marks for things like reserved words or column names that have spaces (never like these anyhow).
From my reading your question and sample tables T1 and T2... T1 appears to be some Lookup table and has IDs and descriptions associated to said IDs. Your T2 table appears to be your detail/transaction based table and it may or not have an actual requirement hence your desire to always include those records without a specific requirement.
If this is the case, it sounds like you want "all detail records that have some condition REGARDLESS of a matched requirement ID as found in the lookup table." If this is accurate, you would be looking for
Select
T2.T1_ID,
coalesce( T1.Statement, '' ) StatementFromT1Table
from
SomeMainTable T2
LEFT JOIN SomeLookupTable T1
on T2.T1_ID = T1.T1_ID
where
T2.T1_ID = SomeIdParameterValue
AND ( T1.T1_ID is NULL
OR T1.Statement = SomeOtherParameterValue )
The join between tables I always try to list the left-side table first, then indent to the right-side table and have my ON condition show the left.column = right.column so you always see the relationship and how table A gets to table B (and nested more as other joins come into play).
The different between (INNER) JOIN and LEFT JOIN is that (INNER) JOIN REQUIRES a record to always match on both tables. LEFT JOIN means I want everything from the table on the left side REGARDLESS of an actual match in the right table.
So at this point, I get all from T2 alias table first regardless of the answer in T1 alias. Now, how to deal with the zero remarks id value. If zero indicates you KNOW there wont be a match in T1, then you can just say I want all records on the T2 side if the T1 side IS NULL... But you also care for a specific statement, hence the OR within the parenthesis test.
The first part of the where is if you were specifically looking for all things of a T1_ID = some value, so that is a primary parameter and only applicable to the T2 side... you are qualifying the T1 side via the AND ( null or other equality test ) condition.
If you have some confidential data, it is ok to randomize / provide sample data, but having real table name reference / context will help us better understand what you are trying to accomplish. Ambiguity in table names and columns does not help us mentally understand and might have better query solutions having a better understanding.
If I am close and you need additional clarification, please advise and/or edit your original post with additional sample data and final output... such as parameters being filtered for too.
POST CLARIFICATION.
Per your comments, here are the clarifications...
The "SomeMainTable T2" is actually a breakdown of the actual table name within your database and "T2" is the ALIAS reference. Imagine your table name is "SomethingReallyLongDetail". Would you prefer to write your query something like
select
SomethingReallyLongDetail.Column1,
SomethingReallyLongDetail.Column7,
SomethingReallyLongDetail.Column20
from
SomethingReallyLongDetail
OR...
select
SRL.Column1,
SRL.Column7,
SRL.Column20
from
SomethingReallyLongDetail SRL
In this case, I used an alias "SRL" to more easily correlate to the table name as an acronym / abbreviation vs having to type the long value over and over, then have more chance of typing mistakes. Simply for readability providing the "alias" reference within the query. So, I did not know your ACTUAL table name, so I made it up but using the "T1" and "T2" references to stay in-line with your original post.
Next, COALESCE(). Since this query does a LEFT-JOIN, The right-side table may (or not) actually have a record match on the ID as you know might not always exist. Since I was trying to pull the "Statement" column from that second table (alias T1), that description could be NULL which you probably would not want to show in any sort of output. To prevent that, COALESCE() says, give me the value from the first parameter in the list... If that value is null, give me the second value. In this case the second value is just an empty string.
Parameters in the query. Your original query had reference to XXX and YYY such as you knew of a specific T1.ID value you wanted to narrow down to pulling out, but a different value YYY as being part of the statement. So the place where you had an "XXX", I just put a place-holder here for you to apply/put any value you were specifically looking for. Similarly for your "YYY" value, another place-holder for that. Just substitute whatever criteria you were looking for.
Finally that AND part of the where clause. This is for the condition of the LEFT-JOIN. Since you KNOW that not all records will have a match in the "T1" secondary table, with the LEFT JOIN, the ID will be found and HAVE a value, or there will not be a value and thus NULL.
If there is no matching record, you would never be able to compare some string, int, date, whatever to a column as it would be null. So I am doing
(T1.T1_ID IS NULL -- as in there was no match
OR T1.Statement = SomeOtherParameterValue ) -- there WAS a match, and I only want where the statement equals a given value.
Per your comments and example results, your query SHOULD be simplified to...
Select
T2.ID,
T2.T1_ID,
T2.Requirement,
coalesce( T1.Statement, '' ) StatementFromT1Table
from
T2
LEFT JOIN T1
on T2.Requirement = T1.T1_ID
where
T2.Requirement = 0
OR T1.T1_ID IS NOT NULL
In your case, the final answer is... I want all records where there is no requirement (thus = 0) OR the record DOES have a match in the T1 table (thus T1.T1_ID IS NOT NULL)
I am thinking that you want a LEFT JOIN:
SELECT 1
FROM `T2` LEFT JOIN
`T1`
ON `T1`.`T1_ID` = `T2`.`REQUIREMENT`
WHERE (`T2`.`REQUIREMENT` <> 0) OR
(`T1`.`STATEMENT` = YYY AND `T2`.`T1_ID` = XXX);
This returns rows for all T2 values where REQUIREMENT != 0. It also returns the rows generated by the JOIN. Of course 1 is not very descriptive, so you want be able to tell which rows are which.
Your question would be much easier to follow with sample data and desired results.
if T2.REQUIREMENT=0 I know for sure, that there will not be any
T1.T1_ID entry that will match the JOIN requirements
So in order to get 1 returned when T2.REQUIREMENT=0, the join must match this condition too:
SELECT 1
FROM `T1` INNER JOIN `T2`
ON `T1`.`T1_ID` = `T2`.`REQUIREMENT` OR `T2`.`REQUIREMENT`=0
WHERE `T2`.`T1_ID`=XXX
AND `T1`.`STATEMENT`=YYY
Edit:
or just append 1s with UNION for all rows that have T2.REQUIREMENT=0:
SELECT 1
FROM `T1` INNER JOIN `T2`
ON `T1`.`T1_ID` = `T2`.`REQUIREMENT`
WHERE `T2`.`T1_ID`=XXX
AND `T1`.`STATEMENT`=YYY
UNION ALL
SELECT 1
FROM `T2`
WHERE `T2.REQUIREMENT=0`
this will work even if T1 is empty.
I need to join / loop over some data but not sure how to do it using only Mysql nested / WHERE IN type queries. I have one table that looks like this
id, code1, code2, code3, code4........... code20
1 12 41 1 55
So a lot of columns, they don't all have values, but of the ones that do, I need to take each of those codes and return a row for the code from a table that looks like this:
codeid, description
1 item1
12 item12
13 item13
41 item41
...
I was hoping I could use a wildcard in my select for the columns like
SELECT description FROM table2 WHERE IN(SELECT code* FROM table1)
It doesn't look like the wildcard is possible from my googling, but someone here may know a trick. How can I take all the values from the first table as a list, run the query on it to return the definitions of each code as separate rows?
No, you cannot use a wildcard. This is a problem with your data structure. Whenever you have columns that are only distinguished by numbers, you probably have an issue with the data model.
Instead, you should have a table with one row per id and per code.
You can do something like:
select t2.description
from table2 t2
where exists (select 1
from table1 t1
where t2.code in (t1.code1, t1.code2, . . . )
);
Performance will not be very good. For that, see the first suggestion for fixing the data model.
query:
select DOG_CD,ANIMAL_CD
from FKAGM
where FKAG = 12024
Displays 3 rows
DOG_CD - ANIMAL_CD are column names and below each column is 3 numerical values yielded from the above query & I have no clue how to draw a table on here to depict that. =(
There is a table called Dog_Animal that has a column called "Name" (Dog_Animal.Name) that I want to join with this above query. I want to join on ANIMAL_CD as FKAGM table and the DOG_ANIMAL table have the ANIMAL_CD column in common. I'd like to display "Name" right next to the ANIMAL_CD column. The issue is when I join the tables it displays like every instance of DOG_CD and ANIMAL_CD within the Dog_Animal table (Which is thousands) something similar to the below illustration. since the Dog_Animal table has thousands of DOG_CD and ANIMAL_CODE fields populated. I just want it to be limited to the three rows that are returned by the above query (Limit or distinct or something) and input the Dog_Animal.Name next to Animal_CD. I've been working on this for an hour and I know it must be so simple, but I can't seem to get it to work. I am not sure if a subquery is needed or exists, or case, or what. If you can figure this out I would be so thankful!
DOG_CD - ANIMAL_CD - Dog_Animal.Name with the same 3 rows of data just now a name included
select
f.DOG_CD,f.ANIMAL_CD,d.name
from FKAGM f
inner join dog_animal d
on d.animal_cd = f.animal_cd
where f.FKAG = 12024;
inner join would work for you. If you only need to limit it to 3 results, add limit 3 order by f.dog_cd at the end of your query.
I have a TABLE1 like this:
And a TABLE2 like this:
I want to delete entries from table 1 whose endTimestamp is not equal to ANY table 2 entry endTimestamp, with a margin of 1000 time units.
(I know in this example all the entries from table 1 and table 2 have the same timestamp values, so the 5 entries from table 1 should be kept, and any other should be erased if existed)
Since the ids of both tables are not related to each other, I can't perform a JOIN operation as long as I know.
How can I do this?
EDIT: Tried here. Works, but does not work at my server :|
You're looking for :
delete from table1 where endTimestamp not in (Select endTimestamp from table2)
Edit : As pointed out by #user2864740, you can very well use Join here too, even if the ids of both tables are not related to each other.
DELETE FROM table1 INNER JOIN table2 ON table1.endTimestamp = table2.endTimestamp;
Here's a question:
Using appropriate column names, show admit id and average obs value for obs type 'CONT' where the average obs value of the CONT is >= 40.
Lets say admit is table1 and observe is table2 but with the same primary key Admit_id. I'm trying to get the result where average of obs value is greater than 40 but
however I got this error instead: Unknown column 'Average' in 'where clause. Any solution here?
Select
ADMIT.Admit_id,
(SELECT AVG(Obs_value) FROM OBSERVE) AS Average
from
ADMIT,OBSERVE
Where
ADMIT.Admit_id=OBSERVE.Admit_id
AND
OBSERVE.Obs_type = 'CONT'
AND
Average >=40;
you should try joining the two tables and you cant reference an alias inside the WHERE .. it has to be HAVING. so something like this..
SELECT a.Admit_id, AVG(o.Obs_value) AS Average
FROM ADMIT a
JOIN OBSERVE o ON o.admit_id = a.admit_id
WHERE o.Obs_type = "CONT"
GROUP BY a.Admit_id
HAVING Average >=40;
Think of it this way...
SELECT is making an order at a restaurant....
FROM and JOIN is saying what menu's you want to order from....
WHERE is any customization you want to make to your order (aka no mushrooms)....
GROUP BY and anything after is after the order has been completed and is at your table...
ORDER BY is saying what dishes you want first (aka i want my entree then dessert then appetizer ).
HAVING can be used to pick out any mushrooms that were accidentally left on the plate....
etc.. I know its a weird analogy but its a good way to understand how it works..
the alias to a table cannot be referenced until you create that table with your select you could also make it a sub select and do the same thing with a WHERE like so
SELECT *
FROM
( ... your_inner_select -- without the HAVING
)t -- every table must have an alias
WHERE t.Average >=40