Select query in MySQL - sql

Two tables
Table1
ID FileName
1 abc
2 abc
3 abc
4 xyz
Table2
ID Table1_ID isDeleted
1 1 1
2 2 1
3 3 0
4 4 0
I need to get the count of filename for the isDeleted=1 by passing any ID of table1, i.e for all the values(1,2,3) of ID, i need the count as 2
I tried with the following query
SELECT COUNT(t1.FileName) FROM Table1 t1
LEFT OUTER JOIN Table1 t11 ON t1.FileName=t11.FileName
INNER JOIN table2 t2 ON t2.Table1_ID =t1.ID AND t2.isDeleted=1
WHERE t1.ID=X;
X-1,2,3
This always returns 3.
Edit: I need to get the count of the filename from the first table by passing the ID from the first table. The count should be based on the isdeleted column in second table. The tables are related by the column ID (table1) and Table1_ID (table2)

Give this a shot:
select SUM(isDeleted)
from Table2
where Table1_ID in (
select ID from Table1
where FileName = (select FileName
from Table1
where ID = 1)
)
Edit: to get file count:
select count(*)
from Table1 a
join Table2 b on a.ID = b.Table1_ID and b.isDeleted = 1
where a.FileName = (select FileName
from Table1
where ID = 1)

This works for me:
declare #id int
set #id = 1 /*Or 2 or 3 or 4, etc.*/
select sum(isdeleted)
from table2
where table1_id in
(select id
from table1
where filename = (select filename
from table1
where id = #id))
Edit: I can't see how this is different from Fosco's answer.

SELECT COUNT(t1.FileName) FROM Table1 t1
INNER JOIN table2 t2 ON t2.Table1_ID =t1.ID AND t2.isDeleted=1
WHERE t1.ID=X;

Related

SQL Select all first items in a list of rows identified by Ids and filtered by a specific Type in another table

I need to create a table keyed by an ID where the values of one of the columns in the new table are the earliest values entered into the column of another table where the rows share the same ID and have a specific type label.
For example, say I want the Name and first Value entered for each fruit with an entry type A:
These are the tables I have:
TABLE1
Key
ID
Name
1
1
Cherry
2
2
Grape
TABLE2
Key
ID
Value
EntryNum
EntryType
1
1
21
1
A
2
1
32
2
B
3
1
4
3
B
4
1
15
4
A
5
2
3
1
B
6
2
8
2
A
7
2
16
3
B
And this is the result that I want:
TABLE3
ID
Name
EarliestEntry
1
Cherry
21
2
Grape
8
I've attempted the following query but it just returns the same value for all EarliestEntry:
SELECT TABLE1.ID, TABLE2.Name,
(SELECT Value FROM (SELECT ROW_NUMBER() OVER (ORDER BY TABLE2.EntryNum)
as row_num, Value FROM TABLE2
WHERE TABLE2.ID = TABLE1.ID AND TABLE2.EntryType = 'A')
AS sub
WHERE row_num = 1) AS EarliestEntry
INTO TABLE3
FROM TABLE2
INNER JOIN TABLE1 ON TABLE1.ID = TABLE2.ID
GROUP BY TABLE1.ID, TABLE2.Type, TABLE2.EntryNum
I would greatly appreciate help on this. Thank you
If you wanted to use the ROW_NUMBER function then you would need to put that on TABLE1 and add a partition by like so:
WITH rn AS(
SELECT a.Key, ROW_NUMBER() OVER(PARTITION BY a.ID ORDER BY a.EntryNum) AS rn
FROM TABLE2 AS a
)
SELECT b.Name, a.Value AS EarliestValue
FROM TABLE2 AS a
INNER JOIN TABLE1 AS b ON b.ID = a.ID
INNER JOIN rn AS rn ON rn.key = a.key
WHERE rn.rn = 1
In your example you skipped the PARTITION BY clause so you just get a number for all values in TABLE2. Instead of a number per ID in ascending order for Value.
Based on your description of the three tables TABLE1, TABLE2 and TABLE3.
I modified a little bit your script. Thank of Dale K remark, I explain in some words the solution : the field TABLE2.Name shown in the first select was wrong, because [name] belongs to TABLE1, so the right syntax for this is TABLE1.name. And in the GROUP BY clause the field TABLE2.Type might be replaced by TABLE1.name to repect aggregation criteria. So the script becomes :
SELECT DISTINCT table1.id, table1.name,
(SELECT Value FROM (SELECT ROW_NUMBER() OVER (ORDER BY table2.EntryNum)
as row_num, Value FROM table2
WHERE table2.id = table1.id AND table2.EntryType = 'A')
AS sub
WHERE row_num = 1) AS EarliestEntry
INTO table3
FROM table2
INNER JOIN table1 ON table1.id = table2.id
GROUP BY table1.id, table1.name, table2.entrynum;
Here, you can verify the output with fiddle
You are hugely over-complicating this.
Just partition Table2 and take a row-number, then join that to Table1 and filter on only row-number 1
SELECT
t1.Id,
t1.Name,
EarliestEntry = t2.Value
FROM Table1 t1
JOIN (
SELECT *,
rn = ROW_NUMBER() OVER (PARTITION BY t2.ID ORDER BY t2.EntryNum)
FROM Table2 t2
WHERE t2.EntryType = 'A'
) t2 ON t2.ID = t1.ID AND t2.rn = 1;
db<>fiddle

SQL Get Count Across 3 Tables

I have a 3 tables, one with these two columns
table1:
id, name
0 foo
1 etc
2 example
table2:
id table1_id
0 1
1 0
2 2
table3:
id table2_id
0 1
1 0
2 0
Which query can I find all 'name's from table1 where ALL ids in table2 have a count of atleast n in table3? i.e if n was 1 it should return foo and etc
EDIT:
Explained poorly, I'm trying to get the name of every record in table1 where ALL corresponding records in table2 (i.e records where the column table1_ID is equal to each id within table1. In my example tables, each ID has one) have a count in table3 of atleast n.
If n was 1, as the table2_id 0 appears twice in records 1 and 2, its 'parent' would be returned. It corresponds to the table 1 record 1, so the name of the record with table1 id: 1 should be returned, which is etc. Example also as it has a count of 1 in the bottom column, however foo does not appear so it shouldnt.
Expected result:
name
foo
etc
You can do this using a subquery in the where clause:
select t1.*
from table1 t1
where (select count(t3.id)
from table2 t2 left join
table3 t3
on t3.table2_id = t2.id
where t2.table1_id = t1.id
group by t2.id
order by count(*) asc -- to get the minimum
limit 1
) >= ? -- value you care about
I suspect that this might have the best performance with appropriate indexes: table2(table1_id, id) and table3(table2_id).
If I have understood the question - if a check on table3.table2_id is greater than 0, the answer would be 'etc' ?
Code below
select t1.name
from
(
select 0 as id, 1 as table2_id
union select 1, 0
union select 2 , 0
) t3
inner join
(
select 0 as id , 1 as table_id
union select 1, 0
union select 2, 2
) t2 on t2.table_id = t3.table2_id
inner join
(
select 0 as id, 'foo' as name
union select 1 , 'etc'
union select 2 , 'example'
) t1 on t1.id = t2.table_id
where t3.table2_id > 0
select table1.name
FROM table1
INNER JOIN table2 ON table1.id=table2.table1_id
INNER JOIN table3 ON table2.id=table3.table2_id
GROUP BY table1.name
HAVING count(*) >= 1
replace the last 1 with whatever n you desire
Here's the sql fiddle if you want to play around with it: http://sqlfiddle.com/#!7/14217/4
Use an INNER join of table1 to table2 and then a LEFT join to table3 and count the corresponding ids of table3.
Then by a 2nd level of aggregation return only the rows of table1 where all the counters are at least 1:
SELECT id, name
FROM (
SELECT t1.id, t1.name, COUNT(t3.id) counter
FROM table1 t1
INNER JOIN table2 t2 ON t2.table1_id = t1.id
LEFT JOIN table3 t3 ON t3.table2_id = t2.id
GROUP BY t1.id, t1.name, t2.id
)
GROUP BY id, name
HAVING MIN(counter) >= 1 -- change to the number that you want
See the demo.
Results:
id
name
0
foo
1
etc

Oracle Sql - I have two tables and need to filter table1 with results from table2. I need to return all of table1 if table2 is empty

I'm currently turning a comma-separated string into a number table with the field name of ID. I'm then trying to do an nvl to select all if the generated table is null.
table1.ID = NVL(table2.ID, table1.ID)
I have two tables and need to filter table1 with results from table2. I need to return all of table1 if table2 is empty.
Scenario I
Table1
ID
1
2
3
4
Table2 (Empty)
ID
Return rows 1, 2, 3, 4
Scenario II
Table1
ID
1
2
3
4
Table2
ID
2
3
Return rows 2, 3
You can use filtering in the where clause:
select t1.id
from table1 t1
where not exists (select 1 from table2) or
exists (select 1 from table2 t2 where t2.id = t1.id);
I don't think join is the right way to express this logic.
You can also use UNION
select t1.id
from table1 t1
where not exists (select 1 from table2 where id = t1.id) union all
select t2.id
from table2 t2
where exist (select 1 from table1 where id = t2.id);

Multiple SELECT with NOT IN - inner Select statement returns empty and the whole SELECT returns empty

There are two table TABLE1 and TABLE2 in which there is a common field ID. I wanted to retrieve values from TABLE2 that doesnot match in TABLE1 based on ID value.
select * from TABLE2 where subject = 1 and ID NOT IN (select ID from TABLE1 where subject = 1)
Sample:
TABLE1 ID SUBJECT 1 1
TABLE2 ID SUBJECT 1 1 2 1
The expected result is 2 and it works fine.
But when TABLE1 is empty or the inner select ID from TABLE1 where subject = 1 returns empty, the whole select statement returns empty.
But the expected result is 1, 2
Is there any way to achieve this ?
Use a left join
select t2.*
from table2 t2
left outer join table1 t1 on t1.id = t2.id and t1.subject = 1
where t2.subject = 1
and t1.id is null
See a good explanation of joins
I think you can use not exists also for this work -
select * from TABLE2 where subject = 1 and NOT exists
(select 1 from TABLE1 where subject = 1 and table1.id = table2.id)

Need help with Join Problem

I have 2 tables
Table 1
ID Status
1 D
2 F
3 D
Table 2
SID ID Approve
1 1 N
2 1 Y
3 1 Y
4 2 Y
5 3 Y
Result:- Should be
Table 1 (ID, Status)
3, D
2,F
Should not display 1 (As one of child rows have N in the Approve Column)
I need a query to joins 2 tables on ID and finds records that don not have N in their Approve column. Does anyone have any clue how to implement this?
I tried
SELECT * FROM Table1 AS t1
INNER JOIN Table2 AS t2
ON t2.id = t1.id
WHERE t2.Approve != 'N'
Doesn’t work
SELECT *
FROM Table1 t1
WHERE NOT EXISTS(SELECT * FROM Table2 t2 WHERE t2.ID = t1.ID AND t2.Approve = 'N')
More efficient and possibly easier to read is the following:
SELECT * FROM Table1 AS t1
LEFT JOIN Table2 AS t2
ON t2.id = t1.id
group by t1.id HAVING sum(t2.approve='Y') = count(t1.id)
Please Try
SELECT distinct t1.*
FROM Table1 AS t1
INNER JOIN Table2 AS tyes
ON tyes.id = t1.id
AND tyes.approve ='Y'
LEFT OUTER JOIN Table2 as tno
ON tno.id = t1.id
AND tno.approve ='N'
where tno.sid is null
It will select any line which is explicitely approved and never disapproved
Select * from table1 where id not in (select id from table2 where approve = 'N')
ID 1 is still returned since there is also a record in table 2 where approve = 'Y' for ID 1.
If you want to exclude any ID where approve is 'N' for any SID then you'll have to work with subqueries; roughly:
SELECT t1.ID,T1.Status FROM Table1 AS t1 INNER JOIN Table2 AS t2 ON t2.id = t1.id
where t1.id NOT IN (select id from Table2 where approve = 'N' and id = t1.id)
regards,
Stijn