These are the two tables Fruit and Fruit_types.There is a m:n relationship between the two tables so we have the third table fruit_type_fruit which has the primary key from the above two tables. The tables look like this
Fruit
ID NAME
1 A
2 B
3 C
Fruit_type
ID LABEL
1 CITRIC
2 DRUPES
3 UNCATALOGUED
Fruit_type_Fruit
Fruit_id Fruit_type
1 1
1 2
1 3
2 1
3 3
Problem Statement: Some fruits even though they have a category(i.e label) get label as Uncatalogued.
For ex:-
A gets the following labels : Citric, drupes and uncatalogued.
B has citric ,
C has Uncatalogued.
Now I need a query to delete all the records which have a suitable label but still have uncatalogued label too.
In the above example
A record which is uncatalogued should be deleted and not
A Citric and Drupes neither
C Uncatalogued.
How about something like this
SQL Fiddle DEMO
DELETE ftf
FROM fruit_type_fruit ftf
WHERE Fruit_type_ID = 3
AND Fruit_ID IN
(
SELECT *
FROM (
SELECT DISTINCT Fruit_ID
FROM fruit_type_fruit f
WHERE f.Fruit_type_ID = 3
) ss
WHERE Fruit_ID IN (
SELECT *
FROM (
SELECT DISTINCT Fruit_ID
FROM fruit_type_fruit f
WHERE f.Fruit_type_ID <> 3
) s)
)
Related
I got two tables. Table one with 3 category columns. Table 2 with 2 category columns. I try to write a query that compare this category columns and shows me the data wich is in one of the threee columns of table 1, but not in one of the two columns of table 2.
e.g.
table 1
ID product cat1 cat2 cat3
10001 product a A B C
10001 product a D E NULL
10001 product a F G H
10002 product b B C D
... ... ... ... ...
table 2
ID product cat1 cat2
10001 product a D E
10001 product a D F
10001 product a G A
10002 product b A C
... ... ... ... ...
The output of the query should look something like that:
product_id not_in_cat
10001 B
10001 C
10001 H
10002 B
10002 D
But i dont know how i can realize it. I tried to do this with a subquery and the "NOT IN" command. But this way i got many subqueries, for each combination of t1.cat1 - t2.cat1, t1.cat2 - t2.cat2, and so on.
And this way i got only the cats which are not in the same row.
Maybe someone can help me to figure out, which way is the best to achieve the desired result.
The query is performed on a MS SQL Server with a openquery to a MySQL and a oracle db server. But i think its more a logic problem.
I think you should "normalize" the data and do the equivalent of a full outer join using union all and group by. This looks like:
select id, cat
from (select id, cat1 as cat, 1 as which from table1 union all
select id, cat2 as cat, 1 as which from table1 union all
select id, cat3 as cat, 1 as which from table1 union all
select id, cat1 as cat, 2 as which from table2 union all
select id, cat2 as cat, 2 as which from table2
) ic
where cat is not null
group by id, cat
having min(which) = max(which);
This finds the categories that are in only one of the tables. Note: If you know that there are no duplicates in either table, then having count(*) = 1 also works.
And, if you want to know the table where the category is present, then ask another question. That is a bit different from the question that you did ask.
I have the following tables:
Table Main:
TestNumber PassageNumber QuestionNumber
1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
Table Child:
TestNumber PassageNumber QuestionNumber User SelectedAnswer
1 1 1 X A
1 2 2 X B
I want to show the data in main table that is not in child table based on a test number and user. So the results i am looking for are the following where the rows from main table are the ones NOT in child:
TestNumber PassageNumber QuestionNumber
1 1 2
1 1 3
1 2 1
1 2 3
I have tried the following query and variations with no luck:
SELECT a.passagenumber, a.questionnumber FROM Main a left outer join
Child b on a.testnumber=b.testnumber where b.user = 'X'
and b.testnumber=1 and a.testnumber=1 and b.selectedanswer is not null
I understand if i had a unique id this would be easy to solve but in this case that is not an option. Any help would be much appreciated.
I thin you can use not in
SELECT a.passagenumber, a.questionnumber FROM Main a
where ( a.testnumber, a.passagenumber, a.questionumber)
not in ( select b.testnumber, b.passagenumber, b.questionumber
from Child b where b.user = 'X' )
Can you join the tables on the three fields, using left join and where the child table value is null?
SELECT p.TestNumber
,p.PassageNumber
,p.QuestionNumber
FROM Parent p
LEFT JOIN Child c ON c.TestNumber = p.TestNumber
AND c.PassageNumber = p.PassageNumber
AND c.QuestionNumber = p.QuestionNumber
AND c.[User] = 'X'
WHERE c.TestNumber IS NULL;
This is a funky question, I know this. And maybe it's all because I'm really tired.
Now, don't blame the design - it is flawed, but nothing I can do anything about, ok?
Two tables, linked by a id-field.
First table contains positions in a warehouse (table P)
Second table contains articles stored on each position in the warehouse (table PA)
ALL positions in the warehouse are present in the P-table (> 5000 records)
Each position could contain more than one article
The are positions in the P-table not present in the PA-table
The count from positionarticles PLUS the positions not present in positionarticles.
Is there really no better way than this utter stupidity?:
SELECT SUM(row)
FROM
(
SELECT COUNT(*) row
FROM PA
UNION
SELECT COUNT(*)
FROM P
WHERE ID NOT IN
(
SELECT P_ID
FROM PA
)
) as rowcounter
Sample data
Table P:
ID Name
1 A01
2 A03
3 B01 *
4 B02 *
Table PA:
ID P_ID A_ID
1 1 201 *
2 1 202 *
3 1 203 *
4 2 205 *
And the count returned is 6 => 4 rows from PA + 2 rows (P_IDs not present in PA). Rows counted are star-marked (*).
Try this:
SELECT P.ID, COUNT(PA.ID) noOfArticles
FROM P
LEFT JOIN PA ON P.ID = PA.P_ID
GROUP BY P.ID
I have a situation where I have to use EAV table design.
I have the following two tables.
Nodes
id name structure_id
1 name 1 7
2 name 2 7
Attributes
id node_id name value structure_id
1 1 firstname test 7
2 1 lastname test 7
3 2 firstname test 7
I have the following query
SELECT n.*, GROUP_CONCAT( CONCAT_WS('||', a.name, a.value) ORDER BY a.name SEPARATOR ';;' ) as _attributes
FROM nodes n JOIN attributes a ON n.structure_id = a.structure_id where n.structure_id = 7
The above query outputs the following (only ONE row)
id: 1
name: name 1
structure_id: 7
_attributes: firstname||test;;firstname||test;;firstname||test;;firstname||test;;lastname||test;;lastname||test
How do I make it to output two rows from nodes table with their rows from attributes?
You will obtain desired result set if join nodes and attributes tables by structure_id and node_id.
Desired result set: "from nodes table with their rows from attributes" .
http://sqlfiddle.com/#!2/83643/1
Good luck
select n.id,n.name,n.structure_id,firstname,lastname from Nodes n
join (select node_id, a.value as firstname from Attributes a where a.name='firstname' ) matches1 on matches1.node_id = n.id
left join (select node_id, a.value as lastname from Attributes a where a.name='lastname' ) matches2 on matches2.node_id = n.id
I'm trying to find the leagues (lid) where two users are apart of.
Here are my tables:
Table leagues:
*id* lname
--------------
1 Hard C
3 Fun
5 Crazy
Table match:
*userid* *lid*
-----------------
1 1
4 5
1 3
2 1
4 1
4 3
*Are primary keys
match.lid is foreign key to leagues.id (a user cannot not be part of the same league twice)
Here's what I have so far (a start):
SELECT t1.lid, t2.lname
FROM match t1
JOIN leagues t2 on t1.lid = t2.id
So far I managed to join the two tables and get the names. My ultimate goal is to show the lid's where two users are part of the same league, say userid 1 and 4.
userid 1 is a member of lid 1 and 3
userid 4 is a member of lid 5, 1, and 3
Both users meet in league(lid) 1 and 3
So I need a query that shows only the league where both users meet. Like this:
lid lname
--------------
1 Hard C
3 Fun
Since userid 1 and 4 meet in league 1 and 3, the results should show that. I can run two queries for each user and check which leagues both users meet via php, but I think it's more efficient to run one query.
SELECT m1.lid, l.lname FROM
`match` m1, `match` m2, leagues l
WHERE m1.lid = m2.lid AND m1.lid = l.id
AND m1.userid = 1
AND m2.userid = 4
There are a few ways. The most straightforward is:
SELECT id AS lid,
lname
FROM leagues
WHERE id IN
( SELECT lid
FROM match
WHERE userid = 1
)
AND id IN
( SELECT lid
FROM match
WHERE userid = 4
)
;
Another way, which is a bit less direct, but may perform better — you can try it and see — is to use JOIN:
SELECT id AS lid,
lname
FROM leagues
JOIN match AS match1
ON match1.lid = leagues.id
AND match1.userid = 1
JOIN match AS match2
ON match2.lid = leagues.id
AND match2.userid = 4
;