SQL join help? Only show results where a child table contains 1 or more records - sql

I'm looking to only show records where a row exists in a child table.
I have two tables. I only want to return records from IP_OP that contain at least 1 record in CD_REVIEWS. I can't figure out how to accomplish this.
SELECT
IP_OP.PATIENT_CTRL_NUM,
IP_OP.ADMIT_HOUR,
CD.REVIEW_DATE
FROM
IP_OP_PATIENT_DET IP_OP,
CD_REVIEWS CD
WHERE
Both tables contain PATIENT_CTRL_NUM.

It depends on which review_date you want ot select, but something like this should work:
SELECT IP_OP.PATIENT_CTRL_NUM,
IP_OP.ADMIT_HOUR,
MAX(CD.REVIEW_DATE)
FROM IP_OP_PATIENT_DET IP_OP
INNER JOIN CD_REVIEWS CD
on IP_OP.PATIENT_CTRL_NUM = CD.PATIENT_CTRL_NUM --or whatever column you need to join on
WHERE .....
GROUP BY IP_OP.PATIENT_CTRL_NUM, IP_OP.ADMIT_HOUR
If you are fine with returning multiple IP_OP_PATIENT_DET records then you could lose the MAX and GROUP BY

SELECT
IP_OP.PATIENT_CTRL_NUM,
IP_OP.ADMIT_HOUR,
CD.REVIEW_DATE
FROM
IP_OP_PATIENT_DET IP_OP INNER JOIN CD_REVIEWS CD
ON IP_OP.PATIENT_CTRL_NUM = CD.PATIENT_CTRL_NUM

Related

SQL select with three tables

Hi guys I'm new with databases and I'm trying to make a query where I join 3 tables. I could make it and I want to clean up the result. I want to know how can I delete the column "pin" from users table and maybe some "ids" columns.
Select * from "wish-list"
Join products
On "wish-list".id = products.holiday_id
Join users
On "wish-list".user_id = users.id
Where "wish-list".id = 1
You need to specify which columns you really need in your output. At the moment you are using
SELECT * which outputs all columns of all joined tables.
Here is what it should look like:
SELECT holiday, products.description, users.pin FROM "wish-list"
JOIN products ON "wish-list".id = products.holiday_id
JOIN users ON "wish-list".user_id = users.id
WHERE "wish-list".id = 1
It's important that you reference all columns which are not your main entity (here wish-list) with tablename.column (products.description and not only description). It will work without referencing strictly but only if the column name is unique in your query.
Furthermore you can rename columns. This is useful for example if you want to get the id's of the product table and the wish-list table.
SELECT product.id AS product_id, id AS wishlist_id FROM "wish-list"
...
Hope that helps!

join two tables and get only first matching row from second table

I want to join three tables.
First table (contacts)contains cid (primary key),name.
Second table (familyInfo) contains fid(primary key),cid (fk),contact name and relationID (fk)
.Third table(relation type) contains relationID(primary key),relationType like father,mother,brother etc ...
Query should join all rows from first table with first matching row from second table .... Contacts which don't have any relation should display null ....only first matching relation should be shown in result
Please help,
Thank you!
I have added image of table structures and expected output for better understanding ...please click here for image
You need to use OUTER APPLY
SELECT c.cid,
c.NAME,
oa.contact_name
FROM contacts c
OUTER APPLY (SELECT TOP 1 f.contact_name
FROM familyInfo f
WHERE c.cid = f.cid
ORDER BY relationID) oa
How it works
Outer apply will return all the records from left table even thought there is no matching record found in right table
Top 1 with Order by will help you find the first matching row from second table

Joining two tables to update results in third table using like

I am trying to join two tables and update the results in the third table.
So table A is the results table and it has the columns customer number and score.
Table B has customer number and ind_code and table C has ind_code and ind_score.
So the output of the query should be such that the ind_code in table B and C should join together based on the first two digits and ind_score should be updated in Table A in the score column. Table A and Table B should be joined on the basis of customer number.
Could anyone please help. I tried multiple queries but nothing seems to work. i am using oracle sql developer
Generally, the JOIN operation mustn't cut field information but if your structure (for me not correct) is that ...
If I understand better:
UPDATE TableA
SET score =
(SELECT MAX(C.ind_score)
FROM TableC C
JOIN TableB B
ON C.ind_code = SUBSTRING(B.ind_code, 1, 2)
WHERE B.customernumber = TableA.customernumber)
I use on subquery MAX aggregate function, because I don't know if your cut of ind_code of TableB can be not unique (i.e. you have ind_code 5555 and 5554)

SQL like clause is not returning any results

I have following query, but it doesn't return any results for where clauses, even when there is row with that kind of name what is queried. If I remove where clause, then all records in Company table which have OfficeLocation table are returned. What is wrong in my query?
SELECT c.*
FROM [MyDb].[dbo].[Company] AS c
INNER JOIN [MyDb].[dbo].[CompanyOfficeLocation] AS col ON c.Id = col.CompanyId
INNER JOIN [MyDb].[dbo].[OfficeLocation] AS ol ON ol.Id = col.OfficeLocationId
WHERE ol.Name like '%Actual Name In This Table%';
Table structure :
Company
Id
etc ...
CompanyOfficeLocation
CompanyId
OfficeLocationId
OfficeLocation
Id
etc ...
Two things for a record to show up given your query:
The OfficeLocation you specified (given the ol.Name value) must have an Id value that is used by a record in the CompanyOfficeLocation table in its OfficeLocationId.
The CompanyOfficeLocation record that you got in #1 must have a CompanyId that exists in the Company table.
If any of those two criteria are not met, then no records will show up in your query result. The INNER JOIN is essentially an 'AND' clause. If a record could not be related to at least one INNER JOINed table, then that record will not show up at all.
If you want a record to show up despite not having any related records in the joined tables, you may want to consider using OUTER JOINs. A RIGHT JOIN in your case to be exact.
I do not find any mistake however I'd suggest you switch the columns after ON when joining to maintain standards.
Instead of - INNER JOIN [MyDb].[dbo].[OfficeLocation] AS ol ON ol.Id = col.OfficeLocationId
Do - INNER JOIN [MyDb].[dbo].[OfficeLocation] AS ol ON col.OfficeLocationId = ol.Id

Some SQL Questions

I have been using SQL for years, but have mostly been using the query designer within SQL Studio (etc.) to put together my queries. I've recently found some time to actually "learn" what everything is doing and have set myself the following fairly simple tasks. Before I begin, I'd like to ask the SOF community their thoughts on the questions, possible answers and any tips they may have.
The questions are;
Find all records w/ a duplicate in a particular column (e.g. a linking id is in more than 1 record throughout table)
SUM price from a linked table within the same query (select within a select?)
Explain the difference between the 4 joins; LEFT, RIGHT, OUTER, INNER
Copy data from one table to another based on SELECT and WHERE criteria
Input welcomed & appreciated.
Chris
I recommend that you start by following some tutorials on this topic. Your questions are not uncommon questions for someone moving from a beginner to intermediate level in SQL. SQLZoo is an excellent resource for learning SQL so consider following that.
In response to your questions:
1) Find all records with a duplicate in a particular column
There are two steps here: find duplicate records and select those records. To find the duplicate records you should be doing something along the lines of:
select possible_duplicate_field, count(*)
from table
group by possible_duplicate_field
having count(*) > 1
What we're doing here is selecting everything from a table, then grouping it by the field we want to check for duplicates. The count function then gives me a count of the number of items within that group. The HAVING clause indicates that we want to filter AFTER the grouping to only show the groups which have more than one entry.
This is all fine in itself but it doesn't give you the actual records that have those values on them. If you knew the duplicate values then you'd write this:
select * from table where possible_duplicate_field = 'known_duplicate_value'
We can use the SELECT within a select to get a list of the matches:
select *
from table
where possible_duplicate_field in (
select possible_duplicate_field
from table
group by possible_duplicate_field
having count(*) > 1
)
2) SUM price from a linked table within the same query
This is a simple JOIN between two tables with a SUM of the two:
select sum(tableA.X + tableB.Y)
from tableA
join tableB on tableA.keyA = tableB.keyB
What you're doing here is joining two tables together where those two tables are linked by a key field. In this case, this is a natural join which operates as you would expect (i.e. get me everything from the left table which has a matching record in the right table).
3) Explain the difference between the 4 joins; LEFT, RIGHT, OUTER, INNER
Consider two tables A and B. The concept of "LEFT" and "RIGHT" in this case are slightly clearer if you read your SQL from left to right. So, when I say:
select x from A join B ...
The left table is "A" and the right table is "B". Now, when you explicitly say "LEFT" the SQL statement you are declaring which of the two tables you are joining is the primary table. What I mean by this is: Which table do I scan through first? Incidentally, if you omit the LEFT or RIGHT, then SQL implicitly uses LEFT.
For INNER and OUTER you are declaring what to do when matches don't exist in one of the tables. INNER declares that you want everything in the primary table (as declared using LEFT or RIGHT) where there is a matching record in the secondary table. Hence, if the primary table contains keys "X", "Y" and "Z", and the secondary table contains keys "X" and "Z", then an INNER will only return "X" and "Z" records from the two tables.
When OUTER is used, we're saying: Give me everything from the primary table and anything that matches from the secondary table. Hence, in the previous example, we'd get "X", "Y" and "Z" records in the output record set. However, there would be NULLs in the fields which should have come from the secondary table for key value "Y" as it doesn't exist in the secondary table.
4) Copy data from one table to another based on SELECT and WHERE criteria
This is pretty trivial and I'm surprised you've never encountered it. It's a simple nested SELECT in an INSERT statement (this may not be supported by your database - if not, try the next option):
insert into new_table select * from old_table where x = y
This assumes the tables have the same structure. If you have different structures then you'll need to specify the columns:
insert into new_table (list, of, fields)
select list, of, fields from old_table where x = y
Let's say you have 2 tables named :
[OrderLine] with the columns [Id, OrderId, ProductId, Qty, Status]
[Product] with [Id, Name, Price]
1) all orderline of command having more than 1 line (it's technically the same as looking for duplicates on OrderId :) :
select OrderId, count(*)
from OrderLine
group by OrderId
having count(*) > 1
2) total price for all order line of the order 1000
select sum(p.Price * ol.Qty) as Price
from OrderLine ol
inner join Product p on ol.ProductId = p.Id
where ol.OrderId = 1000
3) difference between joins:
a inner join b => take all a that has a match with b. if b is not found, a will be not be returned
a left join b => take all a, match them with b, include a even if b is not found
a righ join b => b left join a
a outer join b => (a left join b) union ( a right join b)
4) copy order lines to a history table :
insert into OrderLinesHistory
(CopiedOn, OrderLineId, OrderId, ProductId, Qty)
select
getDate(), Id, OrderId, ProductId, Qty
from
OrderLine
where
status = 'Closed'
To answer #4 and to perhaps show at least some understanding of SQL and the fact this isn't HW, just me trying to learn best practise;
SET NOCOUNT ON;
DECLARE #rc int
if #what = 1
BEGIN
select id from color_mapper where product = #productid and color = #colorid;
select #rc = ##rowcount
if #rc = 0
BEGIN
exec doSavingSPROC #colorid, #productid;
END
END
END