After Table Joining, need specific row value based on another Row with same ID - sql

I have 2 tables as follows:
Table 1:
ID FName
1 Basics
2 Machine1
3 master
4 Machine2
15 Machine3
16 Machine16
Table 2:
ParentID Name InitialValue
1 Active 1
2 MachineName Entrylevel
2 Active 1
3 Active 1
4 MachineName Midlevellevel
4 Active 1
15 MachineName Endlevel
15 Active 1
16 MachineName Miscellenious
16 Active 0
Here, ID of Table 1 is referred as Parent ID at Table 2. I want "Initial Value" of Table 2 for MachineName Rows (of Table 2) provided "InitialValue" of Table 2 for Active Rows (of Table 2) are 1
Result should be like
ID InitialValue
2 Entrylevel
4 Midlevellevel
15 Endlevel

You could join the second table twice, once for MachineName, and once for Active:
SELECT t.ID, machine.InitialValue
FROM table1 t
INNER JOIN table2 machine
ON t.ID = machine.ParentId
AND machine.Name = 'MachineName'
INNER JOIN table2 active
ON t.ID = active.ParentId
AND active.Name = 'Active'
AND active.InitialValue = 1;
About Joins
The JOIN syntax allows you to link records to the previous table in your FROM list, most of the time via a relationship of foreign key - primary key. In a distant past, we used to do that with a WHERE condition, but that really is outdated syntax.
In the above query, that relationship of primary key - foreign key is expressed with t.ID = machine.ParentId in the first case. Note the alias that was defined for table2, so we can refer to it with machine.
Some extra condition(s) are added to the join condition, such as machine.Name = 'MachineName'. Those could just as well have been placed in a WHERE clause, but I like it this way.
Then the same table is joined again, this time with another alias. This time it filters the "Active" 1 records. Note that if the ID in table1 does not have a matching record with those conditions, that parent record will be excluded from the results.
So now we have the table1 records with a matching "MachineName" record and are sure there is an "Active" 1 record for it as well. This is what needs to be output.

Not sure if this is standard SQL but it should work using MySQL.
select T1.ID, T2.InitialValue
from Table1 T1 inner join Table2 T2 on T1.ID = T2.ParentId
where
T2.Name <> 'Active'
and exists (
select * from Table2 T3 where T3.ParentId = T1.ID and T3.Name = 'Active' and T3.InitialValue = 1
)

SELECT t1.ID, t2.InitialValue
FROM table1 t1 join table2 t2 on t1.ID=t2.ParentID
WHERE t2.name LIKE 'MachineName'AND t1.ID= ANY(SELECT t22.ParentID
FROM table2 t22
WHERE t22.InitialValue=1)
I think this should work
//slightly changed the condition in WHERE clausule (t2.parentID changed to t1.ID)

Related

How to determine if there is a missing value in joined table

I am trying to find the "users" that are missing a value in a 2nd table with the value of column "A" = 16 and then column "B" = 0.
I am looking for these values because that would give me the ability to run a query adding a row for each user that is missing the row with the values of A = 16 and B = 0.
So here is the relevant structure of the tables that we would be joining on.
There are two tables, table 1 and table 2
Table 1
ID
parent id
table 2
table1_id
A
B
The problem I am running into is that table2 can have records associated with the table1_id but still needing to verify if the table2 if there is not a row with table1_id, A missing value 16 while B is missing value 0.
Here is the current idea I am working off of for the sql query
SELECT
*
FROM
table1
LEFT JOIN
table2 ON table1.id = table2.table1_id
WHERE
table1.id IS NOT NULL
AND table2.id IS NULL;
This will give me all the table1_ids that are missing records from table2 but does however would not pull the rows where there are rows for the table1_id but however does not determine if there are missing rows with the column A with value 16 or Column B = 0.
If you are able to answer that would be greatly appreciated. I just currently cannot think of a way I can logically create a query that would do this.
So, you want all rows from table 1
And you want rows from table 2 that are A=16, B=0
And you want to know where the relationship breaks down between table1 and table2:
SELECT t1.*
FROM
table1 t1
LEFT JOIN
(
SELECT * FROM table2 WHERE A=16 and B=0
) a16b0
ON
t1.id = a16b0.table1_id
WHERE
a16b0.table1_id IS NULL
There are more ways to skin this cat, but this should be fairly understandable in the sense of "join table1 to (just the a16/b0 rows from table2)"
Another form you might get on with uses EXISTS:
SELECT * FROM table1 t1
WHERE NOT EXISTS(
SELECT null FROM table2 t2
WHERE t2.table1_id = t1.id AND t2.A = 16 AND t2.B = 0
)
In english it's "Select all from table 1 where, for any particular t1 row, there does not exist a t2 row that has: a matching id in table1_id, a 16 in a, a 0 in b"
A slightly less popular form (historical performance reasons probably) would be perhaps:
SELECT * FROM table1 t1
WHERE id NOT IN (
SELECT table1_id FROM table2 WHERE A = 16 AND B = 0
)
"select everything from table1 where the row's id is not in the list of IDs that are a16/b0 from table 2" - in essence this forms a "big list of everything we dont want" and then says "get me everything that isn't in the list of don't-wants"
This is the solution.
SELECT
*
FROM
table1
LEFT JOIN
table1.id = table2.table1_id AND table2.A = 16 AND table2.B = 0
WHERE
table2.id IS NULL;
#jon Armstrong, thanks for the help.

Search Row not exist in another table

Can anyone help me to write the query for below condition.
Table 1
ID Key
1 A
2 A
4 C
5 D
6 A
Table 2
ID Key
2 B
3 B
5 D
6 A
These are the two tables
I want a query in which the ID, which is not exist in Table1 corresponding to Table2, where deleted from table.
Example: ID = 1 row was completely deleted from Table1, and in which key are not match were also deleted
Example: ID = 2, exists in both tables but key are not same so the complete row also delete from Table1 not in Table2, I need a single query which is applicable to both condition
Thanks in advance
SELECT id, [Key]
FROM table1
EXCEPT
SELECT id, [Key]
FROM table2
You can try to check if exists in following:
DELETE FROM Table1
WHERE NOT EXISTS (
SELECT 1
FROM Table2 t2
WHERE Table1.Id = t2.Id
)
OR EXISTS (
SELECT 1
FROM Table2 t2
WHERE Table1.Id = t2.Id AND Table1.[Key] <> t2.[Key]
)
OUTPUT
ID Key
5 D
6 A

How do I Write a SQL Query With a Condition Involving a Second Table?

Table1
...
LogEntryID *PrimaryKey*
Value
ThresholdID - - - Link to the appropriate threshold being applied to this log entry.
...
Table2
...
ThresholdID *PrimaryKey*
Threshold
...
All fields are integers.
The "..." thingies are there to show that these tables hold a lot more imformation than just this. They are set up this way for a reason, and I can't change it at this point.
I need write a SQL statement to select every record from Table1 where the Value field in that particular log record is less than the Threshold field in the linked record of Table2.
I'm newish to SQL, so I know this is a basic question.
If anyone can show me how this SQL statement would be structured, it would be greatly appreciated.
SELECT T1.*
FROM Table1 T1
JOIN Table2 T2 ON T2.ThresholdID = T1.ThresholdID
WHERE T2.Threshold > T1.Value
SELECT t1.*
FROM dbo.Table1 t1 INNER JOIN dbo.Table2 t2 ON t1.ThresholdID = t2.ThresholdID
WHERE t2.Threshold > t1.Value
SELECT * from table1 t1 join table2 t2 on (t1.thresholdId = t2.thresholdId)
where t1.value < t2.threshold;
SELECT t1.LogEntryID, t1.Value, t1.ThresholdID
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.ThresholdID = t2.ThresholdID
WHERE t1.Value < t2.threshold
SELECT * FROM Table1
JOIN Table2
ON table1.ThresholdID = table2.ThresholdID --(assuming table 2 holds the same value to link them together)
WHERE
value < thresholdvalue
A 'JOIN' connects 2 tables based on the 'ON' clause (which can be multipart, using 'AND' and 'OR')
If you have 3 entries in table 2 which share table1's primary key (a one-to-many association) you will receive 3 rows in your result set.
for the tables below, for example:
Table 1:
Key Value
1 Hi
2 Bye
Table 2:
Table1Key 2nd_word
1 You
1 fellow
1 friend
2 now
this query:
SELECT * FROM Table1
JOIN Table2
on table1.key = table2.table1key
gets this result set:
Key Value Table1Key 2nd_word
1 Hi 1 You
1 Hi 1 fellow
1 Hi 1 friend
2 Bye 2 now
Note that JOIN will only return results when there is a match in the 2nd table, it will not return a result if there is no match. You can LEFT JOIN for that (all fields from the second table will be NULL).
JOINs can also be strung together, the result from the previous JOIN is used in place of the original table.

Oracle: Check if rows exist in other table

I've got a query joining several tables and returning quite a few columns.
An indexed column of another table references the PK of one of these joined tables. Now I would like to add another column to the query that states if at least one row with that ID exists in the new table.
So if I have one of the old tables
ID
1
2
3
and the new table
REF_ID
1
1
1
3
then I'd like to get
ID REF_EXISTS
1 1
2 0
3 1
I can think of several ways to do that, but what is the most elegant/efficient one?
EDIT
I tested the performance of the queries provided with 50.000 records in the old table, every other record matched by two rows in the new table, so half of the records have REF_EXISTS=1.
I'm adding average results as comments to the answers in case anyone is interested. Thanks everyone!
Another option:
select O.ID
, case when N.ref_id is not null then 1 else 0 end as ref_exists
from old_table o
left outer join (select distinct ref_id from new_table) N
on O.id = N.ref_id
I would:
select distinct ID,
case when exists (select 1 from REF_TABLE where ID_TABLE.ID = REF_TABLE.REF_ID)
then 1 else 0 end
from ID_TABLE
Provided you have indexes on the PK and FK you will get away with a table scan and index lookups.
Regards
K
Use:
SELECT DISTINCT t1.id,
CASE WHEN t2.ref_id IS NULL THEN 0 ELSE 1 END AS REF_EXISTS
FROM TABLE_1 t1
LEFT JOIN TABLE_2 t2 ON t2.ref_id = t1.id
Added DISTINCT to ensure only unique rows are displayed.
A join could return multiple rows for one id, as it does for id=1 in the example data. You can limit it to one row per id with a group by:
SELECT
t1.id
, COUNT(DISTINCT t2.ref_id) as REF_EXISTS
FROM TABLE_1 t1
LEFT JOIN TABLE_2 t2 ON t2.ref_id = t1.id
GROUP BY t1.id
The group by ensures there's only one row per id. And count(distinct t2.ref_id) will be 1 if a row is found and 0 otherwise.
EDIT: You can rewrite it without a group by, but I doubt that will make things easer:
SELECT
t1.id
, CASE WHEN EXISTS (
SELECT * FROM TABLE_2 t2 WHERE t2.ref_id = t1.id)
THEN 1 ELSE 0 END as REF_EXISTS
, ....
FROM TABLE_1 t1

Query three non-bisecting sets of data

I am retrieving three different sets of data (or what should be "unique" rows). In total, I expect 3 different unique sets of rows because I have to complete different operations on each set of data. I am, however, retrieving more rows than there are in total in the table, meaning that I must be retrieving duplicate rows somewhere. Here is an example of my three sets of queries:
SELECT DISTINCT t1.*
FROM table1 t1
INNER JOIN table2 t2
ON t2.ID = t1.ID
AND t2.NAME = t1.NAME
AND t2.ADDRESS <> t1.ADDRESS
SELECT DISTINCT t1.*
FROM table1 t1
INNER JOIN table2 t2
ON t2.ID = t1.ID
AND t2.NAME <> t1.NAME
AND t2.ADDRESS <> t1.ADDRESS
SELECT DISTINCT t1.*
FROM table1 t1
INNER JOIN table2 t2
ON t2.ID <> t1.ID
AND t2.NAME = t1.NAME
AND t2.ADDRESS <> t1.ADDRESS
As you can see, I am selecting (in order of queries)
Set of data where the id AND name match
Set of data where the id matches but the name does NOT
Set of data where the id does not match but name DOES
I am retrieving MORE rows than exist in T1 when adding up the number of results returned from all three queries which I don't think is logically possible, plus this means I must be duplicating rows (if it is logically possible) somewhere which prevents me from executing different commands against each set (since a row would have another command executed on it).
Can someone find where I'm going wrong here?
Consider if Name is not unique. If you have the following data:
Table 1 Table 2
ID Name Address ID Name Address
0 Jim Smith 1111 A St 0 Jim Smith 2222 A St
1 Jim Smith 2222 B St 1 Jim Smith 3333 C St
Then Query 1 gives you:
0 Jim Smith 1111 A St
1 Jim Smith 2222 B St
Because rows 1 & 2 in Table 1 match rows 1 & 2, respectively in Table 2.
Query 2 gives you nothing.
Query 3 gives you
0 Jim Smith 1111 A St
1 Jim Smith 2222 B St
Because row 1 in Table 1 matches row 2 in Table 2 and row 2 in Table 1 matches row 1 in Table 2. Thus you get 4 rows out of Table 1 when there are only 2 rows in it.
Are you sure that NAME and ID are unique in both tables?
If not, you could have a situation, for example, where table 1 has this:
NAME: Fred
ID: 1
and table2 has this:
NAME: Fred
ID: 1
NAME: Fred
ID: 2
In this case, the record in table1 will be returned by two of your queries: ID and NAME both match, and NAME matches but ID doesn't.
You might be able to narrow down the problem by intersecting each combination of two queries to find out what the duplicates are, e.g.:
SELECT DISTINCT t1.*
FROM table1 t1
INNER JOIN table2 t2
ON t2.ID = t1.ID
AND t2.NAME = t1.NAME
AND t2.ADDRESS <> t1.ADDRESS
INTERSECT
SELECT DISTINCT t1.*
FROM table1 t1
INNER JOIN table2 t2
ON t2.ID = t1.ID
AND t2.NAME <> t1.NAME
AND t2.ADDRESS <> t1.ADDRESS
Assuming that T2.ID has a unique constraint, it is still quite logically possible for this scenario to occur.If for every record in T1, there are two corresponding records in T2:
Same name, same id, different address
Same name, different id, different address
Then the same record for T1 can come up in the first and third query for example.
It is also possible to simultaneously get the same row in the second and third query.
If T2.ID is not guaranteed to be unique, then you could get the same row from T1 in all three queries.
I think the last query could be the one fetching extra set of rows.
i.e. It is relying on Name matching in both tables (and not on ID)
To find the offending data (and help find your logic hole) I would recommend:
(caution pseudo-code)
Limit the results to just SELECT id FROM ....
UNION the result sets
COUNT(id)
GROUP BY id
HAVING count(id) > 1
This will show the records that match more than one sub-query.