I am trying to find duplicates in a table column only if the row is also a child of another table ex:
table 1 columns
id
Type
table 2 columns
id
table1Id
table3Id
Sample Data:
table 1:
id Type
1 aType
2 myType
3 myType
4 aType
5 myType
6 aType
table 2:
id table1Id table3Id
1 1 1
2 2 1
3 4 2
4 5 1
5 6 2
Results I'd like: (rows in table1 with same Type and table3Id)
table1Id table1Type table3Id
2 myType 1
5 myType 1
4 aType 2
6 aType 2
query I tried
select table1.id as table1Id, table1.type as table1Type, table2.table3Id as table3Id
from table1, table2
inner join table1 a on table1.Type = a.Type
where a.id <> table1.id and table1.Type = "myType" and table1.id = table2.table1Id
The above query give me an error "unknown column table1.Type in on clause"
I have no idea if the query is correct, but you are getting the error because of the comma in the from clause. Here is an easy rule: Never use commas in the FROM clause. Always use explicit JOIN syntax.
You can fix your problem directly by using CROSS JOIN:
select table1.id as table1Id, table1.type as table1Type, table2.table3Id as table3Id
from table1 cross join
table2 inner join
table1 a
on table1.Type = a.Type
where a.id <> table1.id and table1.Type = 'myType' and
table1.id = table2.table1Id;
It is better to put the JOIN conditions in an ON clause:
select t1.id as table1Id, t1.type as table1Type, t2.table3Id
from table1 t1 inner join
table2 t2
on t1.id = t2.table1Id inner join
table1 a
on t1.Type = a.Type and a.id <> t1.id
where t1.Type = 'myType' ;
That fixes the syntax error -- which is your question. If this doesn't deliver what you expect, then ask another question with sample data, desired results, and a clearer description of the logic.
Related
i have tables like below,
Table 1 :
ID
FIELD_NAME
1
field_1
2
field_2
3
field_3
Table 2 :
ID
TAG_NAME
1
tag_1
2
tag_2
3
tag_3
4
tag_4
Table 3 :
FIELD_ID
TAG_ID
1
1
1
2
1
3
2
1
3
2
3
3
so table-3 shows :
field1(from table1) connected with all 3 tag id's of table-2
field2(from table1) connected with all tag id=1 of table-2
and
field3(from table1) connected with all tag id=2,3 of table-2
I like to write a MYSQL Query to fetch
for a given tag_name, find all field name which are NOT associated with this
Example :
input = tag_1
output = field_3
Explanation : as field_3 not have any relation with tag_1 id
input = tag_4
output = field_1, field_2, field_3
Explanation : as no field have any relation with tag_4 id
You could check for fields where certain link table entries do not exist...
SELECT
*
FROM
table1
WHERE
NOT EXISTS (
SELECT *
FROM table3
WHERE field_id = table1.id
AND tag_id = (SELECT id FROM table2 WHERE tag_name = 'tag_4')
)
(Please excuse typos, I'm on my phone.)
dbfiddle as borrowed from #nbk : here
You can do it with a CROSS join of table1 to table2 and a LEFT join yo table3 where you return the unmatched rows:
SELECT t2.TAG_NAME, t1.FIELD_NAME
FROM table1 t1 CROSS JOIN table2 t2
LEFT JOIN table3 t3 ON t3.FIELD_ID = t1.ID AND t3.TAG_ID = t2.ID
WHERE t2.TAG_NAME = ? AND t3.FIELD_ID IS NULL
If you want the results as comma separated list you can also group by TAG_NAME and use GROUP_CONCAT():
SELECT t2.TAG_NAME, GROUP_CONCAT(t1.FIELD_NAME) fields
FROM table1 t1 CROSS JOIN table2 t2
LEFT JOIN table3 t3 ON t3.FIELD_ID = t1.ID AND t3.TAG_ID = t2.ID
WHERE t2.TAG_NAME = ? AND t3.FIELD_ID IS NULL
GROUP BY t2.TAG_NAME
Replace ? with the tag that you search for.
See the demo.
Thanks for assisting with the previous query (SQL Query that selects a column in table 1 and uses that to select sum in table 2) of SUM from 2 tables, I now have a additional Condition for 1 of the tables. I would like to add WHERE Group1 = 1 AND IN/OUT = 'OUT'
I have 3 tables,
Names ,Groups
Names ,Payments
Names ,Payments and IN/OUT
I want to only SUM the OUT Payments in Table 3, I am getting total payments only So FAR is have:
SELECT t1.name1, SUM(t2.sale2),SUM(t3.sale3)
FROM table1 t1 JOIN table2 t2 ON t1.name1 = t2.name2
JOIN table3 t3 ON t1.name1 = t3.name3
WHERE group1 = 1
GROUP BY t1.name1
i would also like to add a zero if there is no data to sum instead of removing the whole record, Currently if a name has no payments in Table 3 but has payments in table 2 it deletes the record.
Please check the query below =>
To Get OutPayment group by Name
SELECT t1.Names,SUM(t3.Payments) As OutPayment
FROM TABLE3 as t3
INNER JOIN TABLE1 as t1 ON t1.Names = t3.Names
INNER JOIN TABLE2 as t2 ON t1.Names = t2.Names
WHERE t1.GroupID = 1 AND t3.INOROUT=2 --INOROUT =2 is OUT and 1 is IN
GROUP BY t1.Names;
To Get TotalOutPayment
SELECT SUM(t3.Payments) As TotalOutPayment
FROM TABLE3 as t3
INNER JOIN TABLE1 as t1 ON t1.Names = t3.Names
INNER JOIN TABLE2 as t2 ON t1.Names = t2.Names
WHERE t1.GroupID = 1 AND t3.INOROUT=2; --INOROUT =2 is OUT and 1 is IN
Note: Code is in DBFiddle too Check the Demo Query Link
Consider 3 tables :
Table1
id(pkey) text
col1 text
Example (Table1)
id col1
1 value1
2 value2
Table2
id(pkey) text
name text
Example (Table2)
id name
1 name1
2 name2
3 name3
Table3
table1_id text
table2_id text
Example (Table3)
table1_id table2_id
1 1
2 1
2 2
How do you use joins to select entries(unique) from table 1 such that :
Table1.id == Table3.table1_id
Table2.id == Table3.table2_id
All of Table2.name that are linked to that table1 entry exactly match a given set of strings.
Sample expected :
If the given search set is : ['name1', 'name2']; return all entries from table1 linked to ALL the entries from table3 which have name as 'name1' or 'name2'.
In the considered example, sample valid response :
id col1
2 value2
If I understand correctly, you can use group by and having:
select t3.table1_id
from table3 t3 join
table2 t2
on t3.table2_id = t2.id
group by t3.table1_id
having sum( case when t2.name in (?, ?, ?) then 1 else 0 end) = count(*) and
count(*) = 3; -- number of elements
Note: This assumes that table3 has no duplicates, which is normally the case.
Please use below SQL query for your problem , I have tried it at my end it working for me .
SELECT t1.id
,t1.col1
FROM Table1 AS t1
INNER JOIN Table3 AS t3 ON t1.id = t3.table1_id
INNER JOIN Table2 AS t2 ON t2.id = t3.table2_id
WHERE t2.name = t1.col1
Please check snapshot for the result of this query for better understanding.
I have three tables with following data
Table 3 :
Table1_id Table2_id
1 1
1 2
1 3
2 1
2 3
3 2
Table 2 :
Table2_id Name
1 A
2 B
3 C
Table 1 :
Table1_id Name
1 P
2 Q
3 R
I have a problem where I need to return all table1_id's which have an entry for all Table2_ids's in Table 3.
ie. I want my output to be
Table1_id
1
I found a solution using count().
But is there a way to use all() or exists() to solve the query?
Using NOT IN with excluding LEFT JOIN in a subselect with a CROSS JOIN
select *
from table1
where Table1_id not in (
select t1.Table1_id
from table1 t1
cross join table2 t2
left join table3 t3 using (Table1_id, Table2_id)
where t3.Table1_id is null
)
VS using COUNT()
select table1_id
from table3
group by table1_id
having count(1) = (select count(1) from table2)
Explanation:
The CROSS JOIN
select t1.Table1_id
from table1 t1
cross join table2 t2
represents how table3 would look like, if every item from table1 would be related to every item from table2.
A (natural) left join with table3 will show us which relations really exists. Filtering by where t3.Table1_id is null (excluding LEFT JOIN) we get the missing relations. Using that result for the NOT IN clause, we get only table1 items that have no missing relation with table2.
You can use the following query:
SELECT DISTINCT t1.*
FROM Table2 AS t2
CROSS JOIN Table1 AS t1
WHERE NOT EXISTS (SELECT 1
FROM Table3 AS t3
WHERE t1.Table1_id = t3.Table1_id AND
t2.Table2_id = t3.Table2_id)
to get Table1 records not having a complete set of entries from Table2 in Table3. Then use NOT IN to get the expected result.
Here is a solution using EXISTS and INNER JOIN.
SELECT DISTINCT t3_out.Table1_id FROM Table3 t3_out
WHERE EXISTS( SELECT 1
FROM Table2 t2 INNER JOIN Table3 t3 ON t2.Table2_id = t3.Table2_id
WHERE t3.Table1_id = t3_out.Table1_id
HAVING COUNT(DISTINCT t2.Table2_id) = 3 )
Looks like I am not able to understand some of the solutions given here and in other places, so I decided to ask my own question.
I have three tables. Like this:
table1
id name active
123 item1 1
234 item2 0
345 item3 1 <--- not in table2!!
456 item4 1
567 item5 1
table2
id item_id instock variants deliverytimes
1 123 0 S 21days
2 123 1 M 21days
3 123 2 L 21days
4 456 1 white 10days
5 456 0 black 10days
6 234 0 yellow sold
7 456 1 green sold
8 456 0 red sold
9 567 0 big sold
table3
id item_id description
1 123 Cool Shirt
2 234 Collectors Box
3 345 Comicbook
4 456 Basecap OneSize
5 567 Cool-Mug
I tried several attempts from LEFT JOIN to RIGHT JOIN etc. that all ended up with multiple results that are not DISTINCT in the ID of the first table that I need nor they were complete. Means that if table2 does not comntain item of table1 it won't show in the result.
The closest I got is this:
select * from table1 t1
INNER JOIN (
SELECT * FROM table2
where (deliverytimes!='sold' OR instock>0) LIMIT 1 ) t2
ON t1.id=t2.item_id,
table3 t3
where t1.active = '1'
and t1.id = t2.item_id and t3.item_id = t1.id;
In the end I need a list of:
"id, name, description"
result (as I would like it to be)
id name description
123 item1 Cool Shirt
345 item3 Comicbook
456 item4 Basecap OneSize
that does need to meet this requirements:
"item needs to be t1.active=1"
and
"if items has rows in t2 show only if one row equals (instock>0 or deliverytimes!=sold)"
and
"if item has no rows in t2 show as long as t1.active=1"
Last one is the problem. I never get distinct t1.id when I use other than inner join and with inner join I still miss the rows that are not present in t2 but are still active=1.
When starting to write a query think about what data you want to show. In your case you want to show data from table1 and table3, so join these and select from them. The criteria on table2 belong in the WHERE clause.
The criteria on table2 are:
either no entry in t2 exists
or an entry in t2 exists with instock > 0 or deliverytimes != sold
This means one EXISTS clause, one NOT EXISTS clause, both combined with OR.
select t1.id, t1.name, t3.description
from t1
join t3 on t3.item_id = t1.item_id
where t1.active = 1
and
(
not exists
(
select *
from t2
where t2.item_id = t1.item_id
)
or
exists
(
select *
from t2
where t2.item_id = t1.item_id
and (instock > 0 or deliverytimes != 'sold')
)
);
try this
SELECT DISTINCT(t1.id) as ID, t1.name, t3.description
FROM table1 AS t1
JOIN table2 AS t2 ON t2.item_id = t1.id
LEFT JOIN table3 AS t3 ON t1.id = t3.item_id
if you want to filter you result with active = 1 and != soled filter in where clause
SELECT DISTINCT(t1.id) as ID, t1.name, t3.description
FROM table1 AS t1
JOIN table2 AS t2 ON t2.item_id = t1.id
LEFT JOIN table3 AS t3 ON t1.id = t3.item_id
WHERE t1.active = 1 AND t2.deliverytimes != 'sold'
OR
SELECT DISTINCT(t1.id) as ID, t1.name, t3.description
FROM table1 AS t1
JOIN table2 AS t2 ON t2.item_id = t1.id AND t2.deliverytimes != 'sold'
LEFT JOIN table3 AS t3 ON t1.id = t3.item_id
WHERE t1.active = 1
You can try to link table1 with table2 using Left outer join (this will make sure you will get all records from table1). And now link tbale3 as inner join, this will make sure to get all records which are related with table1.
Table1 LEFT OUTER JOIN TABLE2 and Table1 INNER JOIN table3.
Above is my assumption, you can try the above logic.