selecting qualified records from a group - sql

There are 2 tables. 1 is the primary table and the other has a 1 to many relationship with the primary table. The table with the many relationship has a field that is being used as a flag. So it usually have a value of Y or null.
So I'd like to select rows from the primary table that has records in the 2nd table only if all the rows on the 2nd table has a Y in its field. In other wards, if the Y field has a null or some other value, they don't qualify.
So the logic is if all rows have a Y than, OK, if some rows have yes and some do not have Y, than they don't qualify in the selection.
Hope that's clear.
Thank you.

Something like this should do the trick...
SELECT p.Field
FROM PrimaryTable p
WHERE NOT EXISTS(SELECT * FROM SecondaryTable s WHERE p.ID = s.ID AND (s.Flag <> 'Y' OR s.Flag IS NULL))
I've assumed that either there will always be a record in SecondaryTable for a given PrimaryTable record....OR, if not, then you still want the primary record returned.

SELECT
p.*
FROM
PrimaryTable p,
( select s.ID,
count(*) AllRecs,
sum( case when S.Flag = 'Y' then 1 else 0 end ) as YesRecCount
from
SecondaryTable s
group by
s.ID
having
AllRecs = YesRecCount ) squalified
WHERE
p.ID = squalified.ID

select p.*
from primary_table p
inner join secondary_table s
on p.join_key = s.join_key
and s.flag = 'Y'
where not exists(select null from secondary_table s2 where s2.join_key = p.join_key and (s2.flag is null or s2.flag <> 'Y'))

Related

SQL query - Return 0 for the column if no record found

I will like to see the specific fields returns with 0 value when there is no record found.
Below are my SQL queries that I have tried so far.
SELECT Customer, Address, Number of lines, Date
FROM table_name
WHERE Date = '30-5-2022' AND Customer IN (A, B, C)
What it returns is only 1 row as below.
Customer
Address
Number of Lines
Date
A
3
RF
30-5-2022
But what I expected to see is:
Customer
Address
Number of Lines
Date
A
UK
33
30-5-2022
B
0
0
30-5-2022
C
0
0
30-5-2022
The customer B and C has no record on 30-5-2022 but I will still need to see the rows but certain columns can be 0.
Please advise if anything that I have missed out? Thanks a lot!
Try below query:
SELECT A.Customer, ISNULL(B.Address, 0),
ISNULL(B.[Number of lines],0), ISNULL(B.Date, '30-05-2022') Date
FROM
(
SELECT DISTINCT Customer
FROM table_name
) A
LEFT JOIN table_name B
ON A.Customer = B.Customer
AND B.Date = '30-5-2022'
This will output all the customers present in the table. You can filter the customers with WHERE clause in the end of the above query based on your requirement.
dbfiddle Link
Assuming customers are in one table (cust) and other stuff in another table (table_name) and they are connected with an id called custid, you need some sweet, sweet left join action, such as:
SELECT c.Customer, c.Address, isnull([Number of lines],0), d.Date
FROM cust c left join table_name d on c.custid = d.custid and
d.Date = '30-5-2022' where
c.Customer IN ('A', 'B', 'C')
You need to put A, B, C in a table and left-join the main table to it. All other conditions must then go in the ON clause not the WHERE.
You can use a virtual VALUES clause for this
SELECT Customer, Address, Number of lines, Date
FROM (VALUES
('A'),
('B'),
('C')
) v(Customer)
LEFT JOIN table_name tn ON tn.Customer = v.Customer
AND tn.Date = '30-5-2022';
Alternatively you can pass in a Table Valued Parameter, or use a table variable. Don't forget to add a primary key.
DECLARE #tmp TABLE (Customer varchar(100) PRIMARY KEY);
INSERT #tmp(Customer) VALUES
('A'),
('B'),
('C');
SELECT Customer, Address, Number of lines, Date
FROM #tmp v
LEFT JOIN table_name tn ON tn.Customer = v.Customer
AND tn.Date = '30-5-2022';

Checking 2 tables for identical IDs and returning 1/0 in column if ID in table 1 exists in table 2

I have 2 tables, 1 containing all reservation ids, and 1 containing reservation ids for livestream reservations. I am trying to write a query that checks to see if a reservation id exists in the livestream table, and returns '1' if true & '0' if false. I figure the best way to do this is with a case statement that returns my result if the reservation id exists in the livestream table, but I am running into issues. Is there a better way to do this?
with table_name as(
select
reservation_id
from all_reservations
)
select t.*,
case when exists(l.reservation_id)
then '1'
else '0' end as is_livestream
from livestream_reservations l
left join table name t
on l.reservation_id = t.reservation_id
So long as reservation_id shows up with at most one record in livestream_reservations, this will work for you:
select r.*,
case
when l.reservation_id is null then 0
else 1
end as is_livestream
from reservations r
left join livestream_reservations l
on l.reservation_id = r.reservation_id;
The case relies on the fact that a failure to join to livestream_reservations returns null in all columns from that table.
In case there may be more than one row with the same reservation_id in the livestream_reservations table, then you could do this:
with ls_count as (
select reservation_id, count(*) as count_livestream
from livestream_reservations
group by reservation_id
)
select r.*, coalesce(lc.count_livestream, 0) as count_livestream
from reservations r
left join ls_count lc on lc.reservation_id = r.reservation_id;
I would recommend exists and using booleans:
select r.*,
(exists (select 1 from livestream_reservations lr where lr.reservation_id = r. reservation_id)
) as is_livestream
from reservations r;
There is a good chance that this is faster than other solutions. More importantly, it avoids problems with duplicates in livestream_reservations.

Case statement for join condition

Hi I want to use case statement in where condition or some similar logic.
I want to ignore where condition when there are no rows in tmp_collaboration table and use the condition when table has some rows in it.
Select clbid from tmp_collaboration;
select customer_id, product_id ,clbid
from customers c
where hdr_id = 10
and clbid in (select clbid from tmp_collaboration)
and status = 'y';
Is this what you want?
select customer_id, product_id ,clbid
from customers c
where hdr_id = 10 and status = 'y' and
(clbid in (select clbid from tmp_collaboration) or
not exists (select 1 from tmp_collaboration)
);
why not use a JOIN .. if there are rows in table the rows are involved otherwise not .
select customer_id, product_id ,clbid
from customers c
INNER JOIN tmp_collaboration t on t.clbid = c.clbid
AND hdr_id = 10
AND status = 'y';

Joining tables based on value

I'm having some hard time doing the join function on those two tables. I have simplified the example dataset as there are additional where-clauses involved for the first table however that doesn't seem to be a problem.
I would write the query for joining the two tables below:
select a.prod_code, a.prod_name, b.ref_value from Product_code a
left join Product_reference b on a.prod_code = b.pref_code
where a.prod_code <> 'CURTAIN' and b.ref_value = 'MAN'
The problem I'm facing is that I want to join tables kind of conditionally. I.e. if the ref_type value is 'MAN' in Product_reference table, I do want to join it, otherwise not.
For an example this query would not include "Chair" in the result as it does not have an ref_type 'MAN' available in the "Product_name". What I'd need though is still show it in the query result, just without joined value from the Product_reference table (given that value with ref_type 'MAN' does not exist for it), not leave it out altogether.
Meanwhile Product_name table record 'CURTAIN' should be left off (regardless if Product_reference ref_type 'MAN' exists or not)
Any recommendations?
Product_code
prod_code prod_name
A Table
B Chair
C Window
D Door
E Curtain
Product_reference
pref_code ref_type ref_value
A MAN x
A AUTO y
B AUTO z
C AUTO z1
C MAN x1
D AUTO zxc
E AUTO abc
E MAN cba
Move b.ref_value = 'MAN' to the join predicate:
SELECT a.prod_code, a.prod_name, b.ref_value
FROM Product_code a
LEFT JOIN Product_reference b ON a.prod_code = b.pref_code AND b.ref_value = 'MAN'
WHERE a.prod_code <> 'CURTAIN'
This will accomplish what you want, which is only left joining the data from table b where b.ref_value = 'MAN', instead of removing all other rows from the result set altogether.
Side note, thanks for including your query and sample data in your very well made question. We appreciate it.
you could use a inner join on the distinct product that have 'MAN'
select
a.prod_code
, a.prod_name
, b.ref_value
from Product_code a
inner join (
select distinct pref_code
from Product_reference
where ref_type = 'MAN') t2 on t2.pref_code = a.prod_code
and a.prod_code <> 'CURTAIN'

Simple SQL Server query - If exists in one table need to return Y else N

I have 2 tables. One table employeemaster contains all of my employees in the company. Primary key = EmpNo.
The other table employeeNoTime contains a smaller list of employees that have no benefits. Primary key = EmpNo.
I want to query that will return 2 columns, the EmployeeNo, and Y or N.
Y if the employee number is in the EmployeeNoTime table. Any suggestions?
Although left join seems like the right answer, it runs the risk that duplicates in the second table could result in duplicate results.
For that reason, I think case with a subquery is better:
select m.*,
(case when exists (select 1 from employeenotime n where m.EmployeeNo = n.EmployeeNo)
then 1 else 0
end) as notimeflag
from employeemaster m;
A left join should do the trick:
SELECT m.EmployeeNo, CASE WHEN n.EmployeeNo IS NOT NULL THEN 'Y' ELSE 'N' END
FROM employeemaster m
LEFT JOIN employeeNoTime n ON m.EmployeeNo = n.EmployeeNo